@gnsx/three 0.185.16 → 0.186.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 +10 -82600
- package/build/three.core.js +1309 -807
- package/build/three.module.js +439 -338
- package/build/three.tsl.js +74 -44
- package/build/three.webgpu.js +6036 -2184
- package/build/three.webgpu.nodes.js +6020 -2184
- package/examples/jsm/Addons.js +6 -6
- package/examples/jsm/controls/ArcballControls.js +1 -1
- package/examples/jsm/controls/FirstPersonControls.js +44 -20
- package/examples/jsm/controls/OrbitControls.js +9 -0
- package/examples/jsm/controls/TrackballControls.js +109 -4
- package/examples/jsm/csm/CSMShadowNode.js +13 -0
- package/examples/jsm/exporters/GLTFExporter.js +23 -7
- package/examples/jsm/exporters/USDZExporter.js +2 -2
- package/examples/jsm/generators/CityGenerator.js +377 -45
- package/examples/jsm/generators/ForestGenerator.js +12 -12
- package/examples/jsm/generators/TerrainGenerator.js +49 -37
- package/examples/jsm/generators/TreeGenerator.js +70 -76
- package/examples/jsm/generators/city/BenchGenerator.js +127 -0
- package/examples/jsm/generators/city/CarGenerator.js +479 -0
- package/examples/jsm/generators/city/CityGeneratorUtils.js +31 -0
- package/examples/jsm/generators/city/HydrantGenerator.js +106 -0
- package/examples/jsm/generators/city/InstancedMeshGenerator.js +86 -0
- package/examples/jsm/generators/city/PersonGenerator.js +447 -0
- package/examples/jsm/generators/city/SidewalkGenerator.js +33 -38
- package/examples/jsm/generators/city/SkyscraperGenerator.js +448 -48
- package/examples/jsm/generators/city/StreetTreeGenerator.js +231 -0
- package/examples/jsm/generators/city/StreetlightGenerator.js +100 -0
- package/examples/jsm/generators/city/TrafficlightGenerator.js +106 -0
- package/examples/jsm/generators/city/TrashcanGenerator.js +100 -0
- package/examples/jsm/geometries/BoxLineGeometry.js +1 -1
- package/examples/jsm/geometries/ParametricGeometry.js +1 -1
- package/examples/jsm/geometries/RoundedBoxGeometry.js +1 -1
- package/examples/jsm/gpgpu/CountingSort.js +271 -0
- package/examples/jsm/helpers/LightProbeGridHelper.js +60 -239
- package/examples/jsm/helpers/LightProbeGridHelperWebGL.js +221 -0
- package/examples/jsm/inspector/Extension.js +94 -0
- package/examples/jsm/inspector/Inspector.js +145 -41
- package/examples/jsm/inspector/RendererInspector.js +100 -52
- package/examples/jsm/inspector/extensions/color-grading/ColorGrading.js +2609 -0
- package/examples/jsm/inspector/extensions/color-grading/ColorWheel.js +352 -0
- package/examples/jsm/inspector/extensions/color-grading/CurveEditor.js +599 -0
- package/examples/jsm/inspector/extensions/color-grading/LUT3DStyle.js +1201 -0
- package/examples/jsm/inspector/extensions/color-grading/LUTMath.js +788 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/BrightnessModule.js +72 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/ColorWheelModule.js +112 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/ContrastModule.js +82 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/CurvesModule.js +109 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/ExposureHueModule.js +110 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/ExposureModule.js +73 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/HueModule.js +78 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/ImportedCubeModule.js +89 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/Module.js +285 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/OutputModule.js +101 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/RendererModule.js +225 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/SatVibranceModule.js +102 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/SaturationModule.js +76 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/VibranceModule.js +76 -0
- package/examples/jsm/inspector/extensions/color-grading/modules/WhiteBalanceModule.js +86 -0
- package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphEditor.js +26 -31
- package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphLoader.js +1 -0
- package/examples/jsm/inspector/tabs/Memory.js +0 -2
- package/examples/jsm/inspector/tabs/Settings.js +4 -0
- package/examples/jsm/inspector/tabs/Timeline.js +223 -171
- package/examples/jsm/inspector/tabs/Viewer.js +515 -21
- package/examples/jsm/inspector/ui/List.js +15 -9
- package/examples/jsm/inspector/ui/Profiler.js +170 -14
- package/examples/jsm/inspector/ui/Style.js +269 -23
- package/examples/jsm/inspector/ui/Tab.js +2 -0
- package/examples/jsm/inspector/ui/Values.js +14 -2
- package/examples/jsm/interactive/HTMLMesh.js +19 -3
- package/examples/jsm/lighting/LightProbeGrid.js +484 -889
- package/examples/jsm/lighting/LightProbeGridUtils.js +107 -0
- package/examples/jsm/lighting/LightProbeGridWebGL.js +841 -0
- package/examples/jsm/lighting/vxgi/VXGIConeTracer.js +194 -0
- package/examples/jsm/lighting/vxgi/VXGINode.js +660 -0
- package/examples/jsm/lighting/vxgi/VXGISceneCollector.js +478 -0
- package/examples/jsm/lighting/vxgi/VXGIVolume.js +1430 -0
- package/examples/jsm/lights/SunLight.js +95 -0
- package/examples/jsm/lights/SunLightNode.js +56 -0
- package/examples/jsm/lights/SunLightShadow.js +319 -0
- package/examples/jsm/lights/SunShadowNode.js +312 -0
- package/examples/jsm/loaders/3DMLoader.js +150 -49
- package/examples/jsm/loaders/3MFLoader.js +202 -1
- package/examples/jsm/loaders/FBXLoader.js +81 -5
- package/examples/jsm/loaders/GLTFGaussianSplatLoaderExtension.js +330 -0
- package/examples/jsm/loaders/GLTFLoader.js +79 -14
- package/examples/jsm/loaders/GaussianSplatPLYLoader.js +386 -0
- package/examples/jsm/loaders/KSPLATLoader.js +463 -0
- package/examples/jsm/loaders/MaterialXLoader.js +111 -1010
- package/examples/jsm/loaders/PCDLoader.js +1 -1
- package/examples/jsm/loaders/SPLATLoader.js +139 -0
- package/examples/jsm/loaders/SPZLoader.js +561 -0
- package/examples/jsm/loaders/materialx/MaterialXArchive.js +108 -0
- package/examples/jsm/loaders/materialx/MaterialXDocument.js +878 -0
- package/examples/jsm/loaders/materialx/MaterialXHextile.js +183 -0
- package/examples/jsm/loaders/materialx/MaterialXInterfaceValidation.js +376 -0
- package/examples/jsm/loaders/materialx/MaterialXLog.js +75 -0
- package/examples/jsm/loaders/materialx/MaterialXNodeInterfaceRegistry.js +4 -0
- package/examples/jsm/loaders/materialx/MaterialXNodeLibrary.js +1021 -0
- package/examples/jsm/loaders/materialx/MaterialXSurfaceMappings.js +661 -0
- package/examples/jsm/loaders/materialx/MaterialXUtils.js +57 -0
- package/examples/jsm/loaders/materialx/compile/MaterialXCompileRegistry.js +997 -0
- package/examples/jsm/loaders/materialx/parse/MaterialXParser.js +28 -0
- package/examples/jsm/loaders/usd/USDAParser.js +15 -2
- package/examples/jsm/loaders/usd/USDCParser.js +1 -4
- package/examples/jsm/loaders/usd/USDComposer.js +80 -42
- package/examples/jsm/materials/WoodNodeMaterial.js +6 -108
- package/examples/jsm/misc/RollerCoaster.js +2 -2
- package/examples/jsm/misc/SculptGL.LICENSE.txt +21 -0
- package/examples/jsm/misc/Sculptor.js +1679 -0
- package/examples/jsm/misc/SculptorMesh.js +1504 -0
- package/examples/jsm/misc/SculptorTools.js +1180 -0
- package/examples/jsm/misc/SculptorUtils.js +345 -0
- package/examples/jsm/misc/TubePainter.js +28 -16
- package/examples/jsm/misc/VolumeSlice.js +24 -24
- package/examples/jsm/modifiers/SimplifyModifier.js +63 -556
- package/examples/jsm/objects/GaussianSplat.js +1039 -0
- package/examples/jsm/objects/Sky.js +66 -45
- package/examples/jsm/objects/SkyMesh.js +70 -51
- package/examples/jsm/physics/JoltPhysics.js +1 -1
- package/examples/jsm/postprocessing/AfterimagePass.js +4 -2
- package/examples/jsm/postprocessing/BloomPass.js +2 -2
- package/examples/jsm/postprocessing/GTAOPass.js +1 -1
- package/examples/jsm/postprocessing/OutlinePass.js +5 -5
- package/examples/jsm/postprocessing/SAOPass.js +1 -1
- package/examples/jsm/postprocessing/SSAOPass.js +1 -1
- package/examples/jsm/postprocessing/SSRPass.js +4 -2
- package/examples/jsm/postprocessing/SavePass.js +1 -1
- package/examples/jsm/postprocessing/TAARenderPass.js +1 -1
- package/examples/jsm/postprocessing/UnrealBloomPass.js +30 -13
- package/examples/jsm/renderers/CSS2DRenderer.js +29 -5
- package/examples/jsm/shaders/DepthLimitedBlurShader.js +4 -1
- package/examples/jsm/shaders/ExposureShader.js +1 -1
- package/examples/jsm/shaders/FilmShader.js +2 -1
- package/examples/jsm/transpiler/AST.js +21 -2
- package/examples/jsm/transpiler/GLSLDecoder.js +498 -8
- package/examples/jsm/transpiler/TSLEncoder.js +82 -10
- package/examples/jsm/transpiler/WGSLEncoder.js +33 -4
- package/examples/jsm/tsl/WebGLNodesHandler.js +29 -39
- package/examples/jsm/tsl/display/AfterImageNode.js +2 -0
- package/examples/jsm/tsl/display/AnaglyphPassNode.js +3 -2
- package/examples/jsm/tsl/display/BilateralBlurNode.js +5 -2
- package/examples/jsm/tsl/display/BloomNode.js +55 -30
- package/examples/jsm/tsl/display/DenoiseNode.js +21 -1
- package/examples/jsm/tsl/display/DepthOfFieldNode.js +24 -6
- package/examples/jsm/tsl/display/DotScreenNode.js +11 -11
- package/examples/jsm/tsl/display/FSR1Node.js +8 -4
- package/examples/jsm/tsl/display/GTAONode.js +199 -86
- package/examples/jsm/tsl/display/GaussianBlurNode.js +65 -52
- package/examples/jsm/tsl/display/GodraysNode.js +5 -2
- package/examples/jsm/tsl/display/ImportanceSampledEnvironment.js +2 -2
- package/examples/jsm/tsl/display/LensflareNode.js +5 -2
- package/examples/jsm/tsl/display/OITPassNode.js +352 -0
- package/examples/jsm/tsl/display/OutlineNode.js +2 -0
- package/examples/jsm/tsl/display/ParallaxBarrierPassNode.js +3 -2
- package/examples/jsm/tsl/display/RGBShiftNode.js +9 -9
- package/examples/jsm/tsl/display/RecurrentDenoiseNode.js +7 -4
- package/examples/jsm/tsl/display/RetroPassNode.js +1 -1
- package/examples/jsm/tsl/display/SMAANode.js +22 -61
- package/examples/jsm/tsl/display/SSAAPassNode.js +2 -4
- package/examples/jsm/tsl/display/SSAONode.js +436 -0
- package/examples/jsm/tsl/display/SSGINode.js +5 -2
- package/examples/jsm/tsl/display/SSRNode.js +7 -2
- package/examples/jsm/tsl/display/SSSNode.js +5 -2
- package/examples/jsm/tsl/display/SharpenNode.js +5 -4
- package/examples/jsm/tsl/display/StereoCompositePassNode.js +1 -3
- package/examples/jsm/tsl/display/StereoPassNode.js +1 -3
- package/examples/jsm/tsl/display/TAAUNode.js +22 -125
- package/examples/jsm/tsl/display/TRAANode.js +16 -142
- package/examples/jsm/tsl/display/TemporalReprojectNode.js +21 -15
- package/examples/jsm/tsl/display/depthAwareBlur.js +63 -0
- package/examples/jsm/tsl/display/hashBlur.js +3 -2
- package/examples/jsm/tsl/lighting/ClusteredLightsNode.js +38 -27
- package/examples/jsm/tsl/lighting/LightProbeGridNode.js +136 -0
- package/examples/jsm/tsl/math/voronoiNoise.js +112 -0
- package/examples/jsm/tsl/shadows/TileShadowNode.js +4 -6
- package/examples/jsm/tsl/utils/Raymarching.js +5 -5
- package/examples/jsm/tsl/utils/SoftParticles.js +60 -0
- package/examples/jsm/tsl/utils/TAAUtils.js +195 -0
- package/examples/jsm/utils/BufferGeometryUtils.js +14 -14
- package/examples/jsm/utils/GaussianSplatUtils.js +229 -0
- package/examples/jsm/utils/WebGLTextureUtils.js +1 -1
- package/examples/jsm/utils/WebGPUTextureUtils.js +1 -1
- package/examples/jsm/webxr/WebGLXRFallback.js +2 -16
- package/examples/jsm/webxr/XRControllerModelFactory.js +16 -4
- package/package.json +9 -16
- package/src/Three.Core.js +2 -1
- package/src/Three.TSL.js +73 -43
- package/src/Three.WebGPU.Nodes.js +1 -0
- package/src/Three.WebGPU.js +1 -0
- package/src/animation/AnimationClip.js +15 -2
- package/src/animation/AnimationObjectGroup.js +18 -6
- package/src/animation/AnimationUtils.js +26 -0
- package/src/animation/KeyframeTrack.js +37 -0
- package/src/constants.js +23 -1
- package/src/core/BufferAttribute.js +3 -2
- package/src/core/BufferGeometry.js +1 -1
- package/src/core/InterleavedBuffer.js +5 -1
- package/src/core/Object3D.js +40 -12
- package/src/core/Raycaster.js +4 -0
- package/src/core/RenderTarget.js +99 -9
- package/src/core/RenderTarget3D.js +12 -8
- package/src/extras/Controls.js +0 -8
- package/src/extras/PMREMGenerator.js +99 -205
- package/src/geometries/TorusGeometry.js +1 -1
- package/src/helpers/ArrowHelper.js +2 -0
- package/src/helpers/AxesHelper.js +2 -0
- package/src/helpers/Box3Helper.js +2 -0
- package/src/helpers/BoxHelper.js +2 -0
- package/src/helpers/CameraHelper.js +2 -0
- package/src/helpers/DirectionalLightHelper.js +2 -0
- package/src/helpers/GridHelper.js +2 -0
- package/src/helpers/HemisphereLightHelper.js +2 -0
- package/src/helpers/PlaneHelper.js +2 -0
- package/src/helpers/PointLightHelper.js +2 -0
- package/src/helpers/PolarGridHelper.js +2 -0
- package/src/helpers/SkeletonHelper.js +2 -0
- package/src/helpers/SpotLightHelper.js +2 -0
- package/src/lights/Light.js +0 -10
- package/src/lights/LightShadow.js +43 -12
- package/src/lights/SpotLightShadow.js +18 -0
- package/src/loaders/BufferGeometryLoader.js +5 -0
- package/src/loaders/ImageBitmapLoader.js +3 -1
- package/src/loaders/ObjectLoader.js +8 -5
- package/src/materials/Material.js +80 -57
- package/src/materials/MeshPhysicalMaterial.js +32 -0
- package/src/materials/nodes/Line2NodeMaterial.js +17 -8
- package/src/materials/nodes/MeshPhysicalNodeMaterial.js +42 -5
- package/src/materials/nodes/NodeMaterial.js +19 -13
- package/src/materials/nodes/PointsNodeMaterial.js +2 -1
- package/src/materials/nodes/manager/NodeMaterialObserver.js +282 -55
- package/src/math/Frustum.js +9 -0
- package/src/math/FrustumArray.js +1 -1
- package/src/math/MathUtils.js +5 -3
- package/src/math/Matrix4.js +2 -9
- package/src/math/Plane.js +30 -1
- package/src/math/Quaternion.js +0 -10
- package/src/math/Ray.js +95 -45
- package/src/math/Triangle.js +0 -2
- package/src/math/Vector3.js +2 -2
- package/src/math/Vector4.js +0 -4
- package/src/math/interpolants/BezierInterpolant.js +36 -23
- package/src/nodes/Nodes.js +2 -0
- package/src/nodes/TSL.js +11 -3
- package/src/nodes/accessors/Batch.js +85 -13
- package/src/nodes/accessors/BufferAttributeNode.js +1 -1
- package/src/nodes/accessors/BuiltinNode.js +1 -1
- package/src/nodes/accessors/Instance.js +19 -18
- package/src/nodes/accessors/MaterialNode.js +9 -0
- package/src/nodes/accessors/ModelNode.js +85 -9
- package/src/nodes/accessors/ReferenceBaseNode.js +1 -70
- package/src/nodes/accessors/ReferenceElementNode.js +72 -0
- package/src/nodes/accessors/ReferenceNode.js +1 -70
- package/src/nodes/accessors/Skinning.js +124 -12
- package/src/nodes/accessors/StorageTextureNode.js +7 -3
- package/src/nodes/accessors/Texture3DNode.js +1 -1
- package/src/nodes/accessors/TextureNode.js +51 -21
- package/src/nodes/accessors/TextureSizeNode.js +4 -2
- package/src/nodes/accessors/UniformArrayNode.js +30 -5
- package/src/nodes/code/CodeNode.js +1 -1
- package/src/nodes/code/FunctionNode.js +12 -2
- package/src/nodes/core/ArrayNode.js +2 -2
- package/src/nodes/core/ContextNode.js +57 -4
- package/src/nodes/core/IndexNode.js +69 -4
- package/src/nodes/core/InspectorNode.js +2 -2
- package/src/nodes/core/MRTNode.js +44 -2
- package/src/nodes/core/Node.js +6 -3
- package/src/nodes/core/NodeBuilder.js +65 -50
- package/src/nodes/core/NodeFrame.js +11 -3
- package/src/nodes/core/NodeUtils.js +88 -0
- package/src/nodes/core/PropertyNode.js +8 -0
- package/src/nodes/core/StackNode.js +0 -1
- package/src/nodes/core/StructNode.js +4 -3
- package/src/nodes/core/UniformGroupNode.js +3 -2
- package/src/nodes/core/UniformNode.js +26 -12
- package/src/nodes/core/VarNode.js +0 -1
- package/src/nodes/display/BumpMapNode.js +2 -2
- package/src/nodes/display/ColorAdjustment.js +1 -1
- package/src/nodes/display/PassNode.js +76 -15
- package/src/nodes/display/ScreenNode.js +22 -65
- package/src/nodes/fog/Fog.js +4 -4
- package/src/nodes/functions/BSDF/BRDF_GGX.js +6 -6
- package/src/nodes/functions/BSDF/BRDF_Sheen.js +1 -1
- package/src/nodes/functions/BSDF/DFGLUT.js +2 -1
- package/src/nodes/functions/BSDF/LTC.js +1 -1
- package/src/nodes/functions/PhongLightingModel.js +1 -1
- package/src/nodes/functions/PhysicalLightingModel.js +83 -25
- package/src/nodes/functions/ToonLightingModel.js +2 -2
- package/src/nodes/functions/material/getParallaxCorrectNormal.js +3 -3
- package/src/nodes/gpgpu/AtomicFunctionNode.js +64 -13
- package/src/nodes/gpgpu/BarrierNode.js +13 -4
- package/src/nodes/gpgpu/ComputeBuiltinNode.js +1 -1
- package/src/nodes/gpgpu/ComputeNode.js +20 -17
- package/src/nodes/gpgpu/SubgroupFunctionNode.js +165 -37
- package/src/nodes/gpgpu/WorkgroupInfoNode.js +44 -6
- package/src/nodes/lighting/EnvironmentNode.js +40 -4
- package/src/nodes/lighting/LightsNode.js +20 -4
- package/src/nodes/lighting/ShadowBaseNode.js +158 -1
- package/src/nodes/lighting/ShadowFilterNode.js +2 -106
- package/src/nodes/lighting/ShadowNode.js +22 -91
- package/src/nodes/materialx/{lib/mx_hsv.js → MaterialXColor.js} +3 -6
- package/src/nodes/materialx/{lib/mx_transform_color.js → MaterialXColorTransform.js} +3 -6
- package/src/nodes/materialx/MaterialXCore.js +37 -0
- package/src/nodes/materialx/MaterialXNodes.js +64 -72
- package/src/nodes/materialx/{lib/mx_noise.js → MaterialXNoise.js} +426 -197
- package/src/nodes/math/BitcountNode.js +24 -4
- package/src/nodes/math/MathNode.js +4 -4
- package/src/nodes/math/MathUtils.js +15 -4
- package/src/nodes/math/OperatorNode.js +2 -2
- package/src/nodes/math/PackFloatNode.js +29 -1
- package/src/nodes/math/Packed4x8IntegerNode.js +433 -0
- package/src/nodes/math/UnpackFloatNode.js +30 -2
- package/src/nodes/parsers/GLSLNodeFunction.js +1 -1
- package/src/nodes/pmrem/PMREMNode.js +1 -1
- package/src/nodes/pmrem/PMREMUtils.js +31 -74
- package/src/nodes/shapes/Shapes.js +1 -1
- package/src/nodes/tsl/TSLCore.js +1 -31
- package/src/nodes/utils/EventNode.js +75 -0
- package/src/nodes/utils/LoopNode.js +54 -13
- package/src/nodes/utils/PostProcessingUtils.js +23 -2
- package/src/nodes/utils/RTTNode.js +97 -32
- package/src/nodes/utils/ReflectorNode.js +8 -4
- package/src/nodes/utils/RotateNode.js +85 -8
- package/src/nodes/utils/SpriteUtils.js +58 -23
- package/src/objects/BatchedMesh.js +6 -0
- package/src/objects/InstancedMesh.js +1 -1
- package/src/objects/LOD.js +1 -1
- package/src/objects/Line.js +12 -0
- package/src/objects/Mesh.js +12 -0
- package/src/objects/Points.js +12 -0
- package/src/objects/Sprite.js +12 -0
- package/src/renderers/WebGLRenderer.js +93 -27
- package/src/renderers/common/Animation.js +12 -2
- package/src/renderers/common/Backend.js +38 -10
- package/src/renderers/common/BindGroup.js +0 -1
- package/src/renderers/common/Bindings.js +50 -4
- package/src/renderers/common/BundleGroup.js +4 -0
- package/src/renderers/common/ClippingContext.js +11 -1
- package/src/renderers/common/Color4.js +9 -0
- package/src/renderers/common/Constants.js +0 -5
- package/src/renderers/common/DirectRenderPipeline.js +233 -0
- package/src/renderers/common/Geometries.js +24 -3
- package/src/renderers/common/Info.js +3 -3
- package/src/renderers/common/InspectorBase.js +37 -8
- package/src/renderers/common/Lighting.js +11 -4
- package/src/renderers/common/Pipelines.js +6 -4
- package/src/renderers/common/QuadMesh.js +16 -2
- package/src/renderers/common/RenderContext.js +8 -0
- package/src/renderers/common/RenderList.js +53 -19
- package/src/renderers/common/RenderLists.js +58 -11
- package/src/renderers/common/RenderObject.js +14 -0
- package/src/renderers/common/RenderObjects.js +14 -9
- package/src/renderers/common/RenderPipeline.js +52 -44
- package/src/renderers/common/Renderer.js +226 -55
- package/src/renderers/common/Storage3DTexture.js +16 -0
- package/src/renderers/common/Textures.js +3 -3
- package/src/renderers/common/XRManager.js +79 -72
- package/src/renderers/common/extras/PMREMGenerator.js +76 -144
- package/src/renderers/common/nodes/NodeManager.js +144 -6
- package/src/renderers/common/nodes/NodeStorageBuffer.js +3 -1
- package/src/renderers/common/nodes/NodeUniformBuffer.js +3 -1
- package/src/renderers/shaders/DFGLUTData.js +2 -1
- package/src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl.js +4 -2
- package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +48 -0
- package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +53 -4
- package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +20 -2
- package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +20 -0
- package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +6 -0
- package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +61 -57
- package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +82 -0
- package/src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js +9 -0
- package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +8 -1
- package/src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl.js +15 -0
- package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +4 -0
- package/src/renderers/shaders/ShaderLib.js +1 -0
- package/src/renderers/shaders/UniformsLib.js +16 -0
- package/src/renderers/webgl/WebGLAnimation.js +2 -2
- package/src/renderers/webgl/WebGLCapabilities.js +2 -2
- package/src/renderers/webgl/WebGLLights.js +74 -4
- package/src/renderers/webgl/WebGLMaterials.js +6 -0
- package/src/renderers/webgl/WebGLOutput.js +36 -24
- package/src/renderers/webgl/WebGLProgram.js +3 -0
- package/src/renderers/webgl/WebGLPrograms.js +8 -0
- package/src/renderers/webgl/WebGLRenderLists.js +6 -10
- package/src/renderers/webgl/WebGLShadowMap.js +47 -44
- package/src/renderers/webgl/WebGLTextures.js +7 -7
- package/src/renderers/webgl-fallback/WebGLBackend.js +153 -45
- package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +83 -29
- package/src/renderers/webgl-fallback/utils/WebGLState.js +163 -17
- package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +32 -5
- package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +11 -4
- package/src/renderers/webgpu/WebGPUBackend.js +513 -145
- package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +99 -20
- package/src/renderers/webgpu/nodes/WGSLNodeFunction.js +2 -1
- package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +3 -12
- package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +24 -14
- package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +80 -14
- package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +62 -7
- package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +9 -3
- package/src/renderers/webgpu/utils/WebGPUUtils.js +16 -4
- package/src/renderers/webxr/WebXRManager.js +25 -2
- package/src/scenes/Scene.js +3 -3
- package/src/textures/CompressedArrayTexture.js +16 -0
- package/src/textures/Data3DTexture.js +16 -0
- package/src/textures/DataArrayTexture.js +16 -0
- package/src/textures/DepthTexture.js +3 -3
- package/src/textures/Texture.js +3 -3
- package/src/textures/{Source.js → TextureSource.js} +39 -8
- package/src/utils.js +6 -79
- package/build/three.core.min.js +0 -6
- package/build/three.module.min.js +0 -6
- package/build/three.tsl.min.js +0 -6
- package/build/three.webgpu.min.js +0 -6
- package/build/three.webgpu.nodes.min.js +0 -6
- package/examples/jsm/libs/ecsy.module.js +0 -1792
- package/examples/jsm/loaders/LottieLoader.js +0 -130
- package/src/nodes/functions/BSDF/BRDF_GGX_Multiscatter.js +0 -52
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
import {
|
|
2
|
+
BoxGeometry,
|
|
2
3
|
Group,
|
|
3
|
-
|
|
4
|
+
InstancedMesh,
|
|
5
|
+
Matrix4,
|
|
6
|
+
Quaternion,
|
|
7
|
+
Vector3
|
|
4
8
|
} from '@gnsx/three';
|
|
5
9
|
|
|
6
10
|
import { MeshStandardNodeMaterial } from '@gnsx/three/webgpu';
|
|
7
|
-
import { cameraPosition, color, float, floor, Fn, fract, fwidth, hash, If, mix, mod, mx_fractal_noise_float, mx_noise_float,
|
|
11
|
+
import { cameraPosition, color, float, floor, Fn, fract, fwidth, hash, If, mix, mod, mx_fractal_noise_float, mx_noise_float, positionWorld, smoothstep, step, uint, uniform, varying, vec4 } from '@gnsx/three/tsl';
|
|
8
12
|
|
|
9
13
|
import { SkyscraperGenerator, createSkyscraperMaterial, buildingPalette } from './city/SkyscraperGenerator.js';
|
|
10
14
|
import { SidewalkGenerator } from './city/SidewalkGenerator.js';
|
|
15
|
+
import { StreetlightGenerator } from './city/StreetlightGenerator.js';
|
|
16
|
+
import { TrafficlightGenerator } from './city/TrafficlightGenerator.js';
|
|
17
|
+
import { TrashcanGenerator } from './city/TrashcanGenerator.js';
|
|
18
|
+
import { BenchGenerator } from './city/BenchGenerator.js';
|
|
19
|
+
import { HydrantGenerator } from './city/HydrantGenerator.js';
|
|
20
|
+
import { StreetTreeGenerator } from './city/StreetTreeGenerator.js';
|
|
21
|
+
import { CarGenerator } from './city/CarGenerator.js';
|
|
22
|
+
import { PersonGenerator } from './city/PersonGenerator.js';
|
|
23
|
+
import { bumpNormal } from './city/CityGeneratorUtils.js';
|
|
11
24
|
|
|
12
25
|
/**
|
|
13
26
|
* Lays out a grid of city blocks and fills each lot with a {@link SkyscraperGenerator}
|
|
@@ -31,30 +44,69 @@ class CityGenerator {
|
|
|
31
44
|
this.parameters = Object.assign( {}, CityGenerator.defaults, parameters );
|
|
32
45
|
this.layout = cityLayout( this.parameters );
|
|
33
46
|
|
|
47
|
+
/**
|
|
48
|
+
* The city seed shared by building and proxy materials. Pass this to
|
|
49
|
+
* {@link createBuildingMaterial} to update the palette when rebuilding.
|
|
50
|
+
*
|
|
51
|
+
* @type {UniformNode<uint>}
|
|
52
|
+
*/
|
|
53
|
+
this.seedNode = uniform( this.parameters.seed, 'uint' );
|
|
54
|
+
|
|
34
55
|
this.generators = [];
|
|
56
|
+
|
|
57
|
+
// per-tower box specs recorded during build(), consumed by buildProxy()
|
|
58
|
+
this.towers = [];
|
|
59
|
+
|
|
35
60
|
this.sidewalk = new SidewalkGenerator( {
|
|
36
61
|
width: this.layout.blockW,
|
|
37
62
|
depth: this.layout.blockD,
|
|
38
63
|
height: this.parameters.curbHeight,
|
|
39
64
|
radius: this.parameters.curbRadius
|
|
40
65
|
} );
|
|
66
|
+
|
|
67
|
+
// the street-furniture generators, each instanced across placements the
|
|
68
|
+
// layout hands them ( see buildFurniture )
|
|
69
|
+
this.furniture = {
|
|
70
|
+
streetlight: new StreetlightGenerator(),
|
|
71
|
+
trafficlight: new TrafficlightGenerator(),
|
|
72
|
+
trashcan: new TrashcanGenerator(),
|
|
73
|
+
bench: new BenchGenerator(),
|
|
74
|
+
hydrant: new HydrantGenerator(),
|
|
75
|
+
tree: new StreetTreeGenerator(),
|
|
76
|
+
car: new CarGenerator(),
|
|
77
|
+
person: new PersonGenerator()
|
|
78
|
+
};
|
|
79
|
+
|
|
41
80
|
this.group = null;
|
|
42
81
|
|
|
43
82
|
}
|
|
44
83
|
|
|
45
84
|
build( materials = {} ) {
|
|
46
85
|
|
|
47
|
-
this.
|
|
86
|
+
this.seedNode.value = this.parameters.seed;
|
|
87
|
+
|
|
88
|
+
for ( const generator of this.generators ) generator.dispose();
|
|
89
|
+
this.generators.length = 0;
|
|
90
|
+
|
|
91
|
+
if ( this.group ) {
|
|
92
|
+
|
|
93
|
+
this.group.clear();
|
|
94
|
+
this.group.dispose();
|
|
95
|
+
|
|
96
|
+
}
|
|
48
97
|
|
|
49
98
|
const group = new Group();
|
|
50
99
|
group.name = 'City';
|
|
51
100
|
|
|
101
|
+
this.towers = [];
|
|
102
|
+
|
|
52
103
|
const L = this.layout;
|
|
53
104
|
const random = createRandom( this.parameters.seed );
|
|
54
105
|
|
|
55
106
|
// raise the lots onto rounded sidewalk slabs ( curbs ) when curbHeight > 0
|
|
56
107
|
|
|
57
108
|
const curb = this.parameters.curbHeight;
|
|
109
|
+
const sw = this.parameters.sidewalkWidth;
|
|
58
110
|
const slabs = [];
|
|
59
111
|
|
|
60
112
|
for ( let bx = 0; bx < L.blocksX; bx ++ ) {
|
|
@@ -70,6 +122,11 @@ class CityGenerator {
|
|
|
70
122
|
|
|
71
123
|
}
|
|
72
124
|
|
|
125
|
+
// the lots sit in an inner zone set back from the block edge by the
|
|
126
|
+
// sidewalk width, so a real walking strip is left between the street
|
|
127
|
+
// wall and the curb. buildings front onto that building line.
|
|
128
|
+
const zoneX = blockX + sw, zoneZ = blockZ + sw;
|
|
129
|
+
|
|
73
130
|
for ( let lx = 0; lx < L.lotsX; lx ++ ) {
|
|
74
131
|
|
|
75
132
|
for ( let lz = 0; lz < L.lotsZ; lz ++ ) {
|
|
@@ -83,10 +140,17 @@ class CityGenerator {
|
|
|
83
140
|
|
|
84
141
|
const tall = random();
|
|
85
142
|
|
|
143
|
+
// nearly fill the lot so neighbours abut into a continuous street
|
|
144
|
+
// wall; the small slack goes to the interior side ( a light well )
|
|
145
|
+
const fw = L.innerLotX - ( 0.4 + random() * 1 );
|
|
146
|
+
const fd = L.innerLotZ - ( 0.4 + random() * 1 );
|
|
147
|
+
|
|
148
|
+
const totalHeight = 38 + tall * tall * 114; // a few tall towers, mostly mid-rise
|
|
149
|
+
|
|
86
150
|
const generator = new SkyscraperGenerator( {
|
|
87
151
|
seed: Math.floor( random() * 100000 ),
|
|
88
|
-
totalHeight
|
|
89
|
-
footprint: { width:
|
|
152
|
+
totalHeight,
|
|
153
|
+
footprint: { width: fw, depth: fd },
|
|
90
154
|
floorHeight: 3.4 + random() * 1.8,
|
|
91
155
|
bayWidth: 1.9 + random() * 2.1,
|
|
92
156
|
pierWidth: 0.4 + random() * 0.5,
|
|
@@ -99,12 +163,21 @@ class CityGenerator {
|
|
|
99
163
|
}, materials.building );
|
|
100
164
|
|
|
101
165
|
const building = generator.build();
|
|
102
|
-
|
|
166
|
+
|
|
167
|
+
// place within the lot, fronted toward the streets it borders so its
|
|
168
|
+
// outer faces land on the building line; interior columns stay centred
|
|
169
|
+
const lotLeft = zoneX + lx * L.innerLotX, lotNear = zoneZ + lz * L.innerLotZ;
|
|
170
|
+
const cx = cornerX === - 1 ? lotLeft + fw / 2 : ( cornerX === 1 ? lotLeft + L.innerLotX - fw / 2 : lotLeft + L.innerLotX / 2 );
|
|
171
|
+
const cz = cornerZ === - 1 ? lotNear + fd / 2 : ( cornerZ === 1 ? lotNear + L.innerLotZ - fd / 2 : lotNear + L.innerLotZ / 2 );
|
|
172
|
+
building.position.set( cx, curb, cz );
|
|
103
173
|
building.castShadow = building.receiveShadow = true;
|
|
104
174
|
|
|
105
175
|
group.add( building );
|
|
106
176
|
this.generators.push( generator );
|
|
107
177
|
|
|
178
|
+
// record a plain box matching this tower for the GI proxy
|
|
179
|
+
this.towers.push( { x: cx, y: curb + totalHeight / 2, z: cz, w: fw, h: totalHeight, d: fd } );
|
|
180
|
+
|
|
108
181
|
}
|
|
109
182
|
|
|
110
183
|
}
|
|
@@ -113,7 +186,9 @@ class CityGenerator {
|
|
|
113
186
|
|
|
114
187
|
}
|
|
115
188
|
|
|
116
|
-
|
|
189
|
+
group.add( this.sidewalk.build( slabs ) );
|
|
190
|
+
|
|
191
|
+
group.add( this.buildFurniture( random ) );
|
|
117
192
|
|
|
118
193
|
this.group = group;
|
|
119
194
|
|
|
@@ -121,6 +196,181 @@ class CityGenerator {
|
|
|
121
196
|
|
|
122
197
|
}
|
|
123
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Builds a lightweight stand-in for the city: one instanced box per tower,
|
|
201
|
+
* sized to match, in a single draw call. Intended for cheap global-illumination
|
|
202
|
+
* bakes, where the detailed facades and street furniture are unnecessary and the
|
|
203
|
+
* boxes still cast the same street shadows and bounce the same warm fill.
|
|
204
|
+
*
|
|
205
|
+
* Call after {@link CityGenerator#build}, which records the tower boxes.
|
|
206
|
+
*
|
|
207
|
+
* @return {InstancedMesh} The proxy mesh.
|
|
208
|
+
*/
|
|
209
|
+
buildProxy() {
|
|
210
|
+
|
|
211
|
+
const towers = this.towers;
|
|
212
|
+
|
|
213
|
+
// each box takes its tower's own masonry colour ( same node, keyed off world
|
|
214
|
+
// position ), so the GI bleeds the real per-building tints. mid roughness / metalness
|
|
215
|
+
// give the boxes a soft, part-glazed sky reflection.
|
|
216
|
+
const material = new MeshStandardNodeMaterial( { roughness: 0.4, metalness: 0.4 } );
|
|
217
|
+
material.colorNode = buildingColorNode( this.layout, this.seedNode );
|
|
218
|
+
const mesh = new InstancedMesh( new BoxGeometry( 1, 1, 1 ), material, towers.length );
|
|
219
|
+
mesh.name = 'CityProxy';
|
|
220
|
+
|
|
221
|
+
const matrix = new Matrix4();
|
|
222
|
+
|
|
223
|
+
for ( let i = 0; i < towers.length; i ++ ) {
|
|
224
|
+
|
|
225
|
+
const t = towers[ i ];
|
|
226
|
+
matrix.makeScale( t.w, t.h, t.d );
|
|
227
|
+
matrix.setPosition( t.x, t.y, t.z );
|
|
228
|
+
mesh.setMatrixAt( i, matrix );
|
|
229
|
+
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
mesh.castShadow = true;
|
|
233
|
+
mesh.receiveShadow = true;
|
|
234
|
+
|
|
235
|
+
return mesh;
|
|
236
|
+
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// dresses the sidewalks and roadway with instanced street furniture, walking the
|
|
240
|
+
// curb edge of every block so poles, baskets, trees, pedestrians and parked cars
|
|
241
|
+
// all align to the same grid the buildings and road markings use
|
|
242
|
+
buildFurniture( random ) {
|
|
243
|
+
|
|
244
|
+
const L = this.layout;
|
|
245
|
+
const top = this.parameters.curbHeight; // sidewalk surface the furniture stands on
|
|
246
|
+
const sw = this.parameters.sidewalkWidth;
|
|
247
|
+
const group = new Group();
|
|
248
|
+
group.name = 'StreetFurniture';
|
|
249
|
+
|
|
250
|
+
const lights = [], signals = [], cans = [], benches = [], hydrants = [], trees = [], people = [], cars = [];
|
|
251
|
+
|
|
252
|
+
// the kerbside mix of a New York street: yellow cabs over an almost
|
|
253
|
+
// entirely grayscale fleet ( black livery cars, whites, silvers,
|
|
254
|
+
// graphites ), with a dark navy, a burgundy or a bronze only here and
|
|
255
|
+
// there. cumulative weights, so common colours repeat like they do kerb
|
|
256
|
+
// to kerb
|
|
257
|
+
const carColor = () => {
|
|
258
|
+
|
|
259
|
+
const r = random();
|
|
260
|
+
for ( const [ threshold, color ] of CAR_COLORS ) if ( r < threshold ) return color;
|
|
261
|
+
return CAR_COLORS[ CAR_COLORS.length - 1 ][ 1 ];
|
|
262
|
+
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
for ( let bx = 0; bx < L.blocksX; bx ++ ) {
|
|
266
|
+
|
|
267
|
+
for ( let bz = 0; bz < L.blocksZ; bz ++ ) {
|
|
268
|
+
|
|
269
|
+
const blockX = - L.cityW / 2 + bx * ( L.blockW + L.street );
|
|
270
|
+
const blockZ = - L.cityD / 2 + bz * ( L.blockD + L.street );
|
|
271
|
+
const edges = blockEdges( blockX, blockZ, L.blockW, L.blockD );
|
|
272
|
+
|
|
273
|
+
for ( const e of edges ) {
|
|
274
|
+
|
|
275
|
+
const len = e.length;
|
|
276
|
+
|
|
277
|
+
// cars on opposite kerbs of a street face opposite ways ( with the
|
|
278
|
+
// traffic on their side ), keyed off which way the kerb faces
|
|
279
|
+
const fdir = Math.sign( e.nx + e.nz ) || 1;
|
|
280
|
+
|
|
281
|
+
// a point on the sidewalk, `lateral` metres in from the curb
|
|
282
|
+
const onWalk = ( t, lateral ) => place( e.x0 + e.dx * t - e.nx * lateral, top, e.z0 + e.dz * t - e.nz * lateral, e.nx, e.nz );
|
|
283
|
+
|
|
284
|
+
// streetlights spaced along the curb, facing the road so the arm reaches over it
|
|
285
|
+
const lc = Math.max( 1, Math.round( len / 30 ) );
|
|
286
|
+
for ( let i = 0; i < lc; i ++ ) lights.push( onWalk( len * ( i + 0.5 ) / lc, 0.8 ) );
|
|
287
|
+
|
|
288
|
+
// street trees in curbside pits, offset from the lights, clear of the corners
|
|
289
|
+
const tc = Math.max( 1, Math.round( len / 16 ) );
|
|
290
|
+
for ( let i = 0; i < tc; i ++ ) {
|
|
291
|
+
|
|
292
|
+
const t = len * ( i + 0.5 ) / tc + 5;
|
|
293
|
+
if ( t > 7 && t < len - 7 && random() < 0.85 ) {
|
|
294
|
+
|
|
295
|
+
// random yaw and height so no two street trees read as copies
|
|
296
|
+
trees.push( placeYawScale( e.x0 + e.dx * t - e.nx * 1.5, top, e.z0 + e.dz * t - e.nz * 1.5, random() * Math.PI * 2, 0.8 + random() * 0.5 ) );
|
|
297
|
+
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// a single hydrant on the kerb, its no-parking zone honoured below
|
|
303
|
+
const hydT = len * ( 0.25 + random() * 0.5 );
|
|
304
|
+
hydrants.push( onWalk( hydT, 0.7 ) );
|
|
305
|
+
|
|
306
|
+
// a bench facing the street on some edges
|
|
307
|
+
if ( random() < 0.4 ) benches.push( onWalk( len * ( 0.3 + random() * 0.4 ), 1.7 ) );
|
|
308
|
+
|
|
309
|
+
// pedestrians scattered across the walking strip, facing any way
|
|
310
|
+
const pc = Math.max( 2, Math.round( len / 9 ) );
|
|
311
|
+
for ( let i = 0; i < pc; i ++ ) {
|
|
312
|
+
|
|
313
|
+
if ( random() < 0.7 ) {
|
|
314
|
+
|
|
315
|
+
const t = len * ( i + random() ) / pc;
|
|
316
|
+
const lateral = 0.9 + random() * ( sw - 2 );
|
|
317
|
+
people.push( placeYawScale( e.x0 + e.dx * t - e.nx * lateral, top, e.z0 + e.dz * t - e.nz * lateral, random() * Math.PI * 2, 0.92 + random() * 0.16 ) );
|
|
318
|
+
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// parked cars in the kerb lane, nose-to-tail with gaps, clear of the
|
|
324
|
+
// corners ( daylighting ) and the hydrant
|
|
325
|
+
for ( let t = 9; t < len - 9; t += 5.8 ) {
|
|
326
|
+
|
|
327
|
+
if ( Math.abs( t - hydT ) > 3 && random() < 0.72 ) {
|
|
328
|
+
|
|
329
|
+
cars.push( { matrix: place( e.x0 + e.dx * t + e.nx * 1.5, 0, e.z0 + e.dz * t + e.nz * 1.5, e.dx * fdir, e.dz * fdir ), color: carColor() } );
|
|
330
|
+
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// the occasional vehicle out in a travel lane
|
|
336
|
+
for ( let t = 14; t < len - 14; t += 13 ) {
|
|
337
|
+
|
|
338
|
+
if ( random() < 0.4 ) cars.push( { matrix: place( e.x0 + e.dx * t + e.nx * 5.5, 0, e.z0 + e.dz * t + e.nz * 5.5, e.dx * fdir, e.dz * fdir ), color: carColor() } );
|
|
339
|
+
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// at two opposite corners: a mast-arm signal reaching over the crossing,
|
|
345
|
+
// and a litter basket on every corner just along the kerb
|
|
346
|
+
const corners = [[ 0, 0 ], [ 1, 0 ], [ 0, 1 ], [ 1, 1 ]];
|
|
347
|
+
for ( const [ cx, cz ] of corners ) {
|
|
348
|
+
|
|
349
|
+
const x = blockX + cx * L.blockW, z = blockZ + cz * L.blockD;
|
|
350
|
+
const ix = cx ? - 1 : 1, iz = cz ? - 1 : 1; // inward, toward the block centre
|
|
351
|
+
|
|
352
|
+
if ( cx === cz ) signals.push( place( x + ix * 1.4, top, z + iz * 1.4, - ix, - iz ) );
|
|
353
|
+
cans.push( place( x + ix * 2.2, top, z + iz * 2.2, ix, iz ) );
|
|
354
|
+
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
group.add( this.furniture.streetlight.build( lights ) );
|
|
362
|
+
group.add( this.furniture.trafficlight.build( signals ) );
|
|
363
|
+
group.add( this.furniture.trashcan.build( cans ) );
|
|
364
|
+
group.add( this.furniture.bench.build( benches ) );
|
|
365
|
+
group.add( this.furniture.hydrant.build( hydrants ) );
|
|
366
|
+
group.add( this.furniture.tree.build( trees ) );
|
|
367
|
+
group.add( this.furniture.person.build( people ) );
|
|
368
|
+
group.add( this.furniture.car.build( cars ) );
|
|
369
|
+
|
|
370
|
+
return group;
|
|
371
|
+
|
|
372
|
+
}
|
|
373
|
+
|
|
124
374
|
dispose() {
|
|
125
375
|
|
|
126
376
|
for ( const generator of this.generators ) generator.dispose();
|
|
@@ -128,6 +378,10 @@ class CityGenerator {
|
|
|
128
378
|
|
|
129
379
|
this.sidewalk.dispose();
|
|
130
380
|
|
|
381
|
+
for ( const key in this.furniture ) this.furniture[ key ].dispose();
|
|
382
|
+
|
|
383
|
+
if ( this.group ) this.group.dispose();
|
|
384
|
+
|
|
131
385
|
this.group = null;
|
|
132
386
|
|
|
133
387
|
}
|
|
@@ -143,19 +397,39 @@ CityGenerator.defaults = {
|
|
|
143
397
|
blocksX: 2,
|
|
144
398
|
blocksZ: 2,
|
|
145
399
|
curbHeight: 0.15, // ~6 in standard curb reveal / sidewalk height above the road
|
|
146
|
-
curbRadius: 5
|
|
400
|
+
curbRadius: 5,
|
|
401
|
+
sidewalkWidth: 5 // walkable strip between the street wall and the curb ( NYC ~15 ft )
|
|
147
402
|
};
|
|
148
403
|
|
|
404
|
+
// kerbside paint mix sampled from Manhattan street photos: cumulative
|
|
405
|
+
// probability thresholds and the paint they select
|
|
406
|
+
const CAR_COLORS = [
|
|
407
|
+
[ 0.22, 0xf5c518 ], // yellow cab
|
|
408
|
+
[ 0.42, 0x111216 ], // black ( livery sedans and SUVs )
|
|
409
|
+
[ 0.59, 0xe9e8e3 ], // white
|
|
410
|
+
[ 0.72, 0xb2b5b8 ], // silver
|
|
411
|
+
[ 0.84, 0x3e4247 ], // graphite
|
|
412
|
+
[ 0.90, 0x74787c ], // mid grey
|
|
413
|
+
[ 0.95, 0x1c2a3f ], // dark navy
|
|
414
|
+
[ 0.98, 0x571f1f ], // burgundy
|
|
415
|
+
[ 1.01, 0x5c4834 ] // bronze
|
|
416
|
+
];
|
|
417
|
+
|
|
149
418
|
// derives the block / street dimensions from the parameters
|
|
150
419
|
function cityLayout( parameters ) {
|
|
151
420
|
|
|
152
|
-
const { street, lot, lotsX, lotsZ, blocksX, blocksZ } = parameters;
|
|
421
|
+
const { street, lot, lotsX, lotsZ, blocksX, blocksZ, sidewalkWidth } = parameters;
|
|
153
422
|
|
|
154
423
|
const blockW = lotsX * lot;
|
|
155
424
|
const blockD = lotsZ * lot;
|
|
156
425
|
|
|
426
|
+
// the lots tile the inner zone left after the sidewalk strip is taken from
|
|
427
|
+
// every edge; buildings front onto its perimeter ( the building line )
|
|
428
|
+
const innerLotX = ( blockW - 2 * sidewalkWidth ) / lotsX;
|
|
429
|
+
const innerLotZ = ( blockD - 2 * sidewalkWidth ) / lotsZ;
|
|
430
|
+
|
|
157
431
|
return {
|
|
158
|
-
street, lot, lotsX, lotsZ, blocksX, blocksZ, blockW, blockD,
|
|
432
|
+
street, lot, lotsX, lotsZ, blocksX, blocksZ, blockW, blockD, sidewalkWidth, innerLotX, innerLotZ,
|
|
159
433
|
cityW: blocksX * blockW + ( blocksX - 1 ) * street,
|
|
160
434
|
cityD: blocksZ * blockD + ( blocksZ - 1 ) * street
|
|
161
435
|
};
|
|
@@ -178,25 +452,51 @@ function createRandom( seed ) {
|
|
|
178
452
|
|
|
179
453
|
}
|
|
180
454
|
|
|
181
|
-
// ---
|
|
455
|
+
// --- furniture placement -------------------------------------------------
|
|
456
|
+
|
|
457
|
+
// the four curb edges of a block: each carries a start corner, a unit direction
|
|
458
|
+
// along the edge, the outward normal ( toward the road ) and a length. furniture
|
|
459
|
+
// walks these, insetting against the normal to sit on the sidewalk.
|
|
460
|
+
function blockEdges( x, z, w, d ) {
|
|
461
|
+
|
|
462
|
+
return [
|
|
463
|
+
{ x0: x, z0: z, dx: 1, dz: 0, nx: 0, nz: - 1, length: w },
|
|
464
|
+
{ x0: x, z0: z + d, dx: 1, dz: 0, nx: 0, nz: 1, length: w },
|
|
465
|
+
{ x0: x, z0: z, dx: 0, dz: 1, nx: - 1, nz: 0, length: d },
|
|
466
|
+
{ x0: x + w, z0: z, dx: 0, dz: 1, nx: 1, nz: 0, length: d }
|
|
467
|
+
];
|
|
468
|
+
|
|
469
|
+
}
|
|
182
470
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
// Mikkelsen's surface-gradient method so the relief actually perturbs the normal.
|
|
187
|
-
function bumpNormal( height ) {
|
|
471
|
+
const _f = /*@__PURE__*/ new Vector3();
|
|
472
|
+
const _r = /*@__PURE__*/ new Vector3();
|
|
473
|
+
const _up = /*@__PURE__*/ new Vector3( 0, 1, 0 );
|
|
188
474
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
const r2 = normalView.cross( dpdx );
|
|
193
|
-
const det = dpdx.dot( r1 );
|
|
194
|
-
const grad = det.sign().mul( height.dFdx().mul( r1 ).add( height.dFdy().mul( r2 ) ) );
|
|
475
|
+
// a placement matrix at ( x, y, z ) whose local +Z faces ( faceX, faceZ ) in the
|
|
476
|
+
// XZ plane, so a canonical model authored facing +Z turns to face that way
|
|
477
|
+
function place( x, y, z, faceX, faceZ ) {
|
|
195
478
|
|
|
196
|
-
|
|
479
|
+
_f.set( faceX, 0, faceZ ).normalize();
|
|
480
|
+
_r.crossVectors( _up, _f ).normalize();
|
|
481
|
+
return new Matrix4().makeBasis( _r, _up, _f ).setPosition( x, y, z );
|
|
197
482
|
|
|
198
483
|
}
|
|
199
484
|
|
|
485
|
+
const _q = /*@__PURE__*/ new Quaternion();
|
|
486
|
+
const _pos = /*@__PURE__*/ new Vector3();
|
|
487
|
+
const _sca = /*@__PURE__*/ new Vector3();
|
|
488
|
+
|
|
489
|
+
// a placement with a free yaw and a uniform scale, so repeated instances ( trees,
|
|
490
|
+
// pedestrians ) read as individuals rather than copies
|
|
491
|
+
function placeYawScale( x, y, z, yaw, scale ) {
|
|
492
|
+
|
|
493
|
+
_q.setFromAxisAngle( _up, yaw );
|
|
494
|
+
return new Matrix4().compose( _pos.set( x, y, z ), _q, _sca.set( scale, scale, scale ) );
|
|
495
|
+
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// --- road material -------------------------------------------------------
|
|
499
|
+
|
|
200
500
|
// antialiased filled band: 1 where |coord| < halfWidth, edge sized to the
|
|
201
501
|
// pixel footprint ( fwidth ) so thin road paint stays crisp and doesn't shimmer
|
|
202
502
|
function lineAA( coord, halfWidth ) {
|
|
@@ -218,13 +518,19 @@ function gridLine( coord, period, halfWidth ) {
|
|
|
218
518
|
}
|
|
219
519
|
|
|
220
520
|
/**
|
|
221
|
-
* The
|
|
222
|
-
*
|
|
521
|
+
* The per-tower flat masonry colour: one palette entry per lot, picked by hashing the
|
|
522
|
+
* lot's grid cell from world position. Keyed off `positionWorld`, so it colours anything
|
|
523
|
+
* standing on the city grid identically, the towers and their {@link CityGenerator#buildProxy}
|
|
524
|
+
* boxes alike.
|
|
525
|
+
*
|
|
526
|
+
* @param {Object} layout - The city layout.
|
|
527
|
+
* @param {number|Node<uint>} [seed=0] - The city seed or a shared seed node.
|
|
528
|
+
* @return {Node<vec3>} The tower colour.
|
|
223
529
|
*/
|
|
224
|
-
function
|
|
530
|
+
function buildingColorNode( layout, seed = 0 ) {
|
|
225
531
|
|
|
226
|
-
// every tower takes one flat colour, picked by hashing its lot
|
|
227
|
-
//
|
|
532
|
+
// every tower takes one flat colour, picked by hashing its lot; common tones repeat
|
|
533
|
+
// so the equal-probability pick feels real
|
|
228
534
|
const palette = buildingPalette.map( hex => color( hex ) );
|
|
229
535
|
|
|
230
536
|
const periodX = layout.blockW + layout.street;
|
|
@@ -233,9 +539,14 @@ function createBuildingMaterial( layout, seed = 0 ) {
|
|
|
233
539
|
const gz = positionWorld.z.add( layout.cityD / 2 );
|
|
234
540
|
const blockIX = floor( gx.div( periodX ) );
|
|
235
541
|
const blockIZ = floor( gz.div( periodZ ) );
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const
|
|
542
|
+
// cells align to the inner-lot grid each tower sits in, so an inset, fronted
|
|
543
|
+
// tower maps wholly to its own cell and reads as one flat colour
|
|
544
|
+
const lotIX = floor( gx.sub( blockIX.mul( periodX ) ).sub( layout.sidewalkWidth ).div( layout.innerLotX ) ).clamp( 0, layout.lotsX - 1 );
|
|
545
|
+
const lotIZ = floor( gz.sub( blockIZ.mul( periodZ ) ).sub( layout.sidewalkWidth ).div( layout.innerLotZ ) ).clamp( 0, layout.lotsZ - 1 );
|
|
546
|
+
const cellX = blockIX.mul( layout.lotsX ).add( lotIX );
|
|
547
|
+
const cellZ = blockIZ.mul( layout.lotsZ ).add( lotIZ );
|
|
548
|
+
const seedHash = typeof seed === 'number' ? uint( ( seed * 2654435761 ) >>> 0 ) : uint( seed ).toVar().mul( uint( 2654435761 ) );
|
|
549
|
+
const cellKey = uint( cellX.add( 4096 ) ).mul( uint( 73856093 ) ).bitXor( uint( cellZ.add( 4096 ) ).mul( uint( 19349663 ) ) ).bitXor( seedHash ).toVar();
|
|
239
550
|
const cellHash = ( a, b ) => hash( cellKey.add( uint( Math.round( ( a + b * 7 ) * 100 ) ) ) );
|
|
240
551
|
|
|
241
552
|
const pick = cellHash( 127.1, 311.7 );
|
|
@@ -243,8 +554,22 @@ function createBuildingMaterial( layout, seed = 0 ) {
|
|
|
243
554
|
for ( let i = 1; i < palette.length; i ++ ) buildingBase = mix( buildingBase, palette[ i ], step( i / palette.length, pick ) );
|
|
244
555
|
buildingBase = buildingBase.mul( cellHash( 269.5, 183.3 ).mul( 0.12 ).add( 0.94 ) ); // subtle per-building brightness
|
|
245
556
|
|
|
557
|
+
return buildingBase;
|
|
558
|
+
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* The shared material every tower in a {@link CityGenerator} is dressed with: the per-lot
|
|
563
|
+
* {@link buildingColorNode} resolved once per vertex on a skyscraper material.
|
|
564
|
+
*
|
|
565
|
+
* @param {Object} layout - The city layout.
|
|
566
|
+
* @param {number|Node<uint>} [seed=0] - A fixed seed, or {@link CityGenerator#seedNode} for a changing city.
|
|
567
|
+
* @return {MeshStandardNodeMaterial} The building material.
|
|
568
|
+
*/
|
|
569
|
+
function createBuildingMaterial( layout, seed = 0 ) {
|
|
570
|
+
|
|
246
571
|
// the pick is constant across a tower, so resolve it once per vertex ( varying )
|
|
247
|
-
return createSkyscraperMaterial( varying(
|
|
572
|
+
return createSkyscraperMaterial( varying( buildingColorNode( layout, seed ) ) );
|
|
248
573
|
|
|
249
574
|
}
|
|
250
575
|
|
|
@@ -255,41 +580,48 @@ function createBuildingMaterial( layout, seed = 0 ) {
|
|
|
255
580
|
function createRoadMaterial( layout ) {
|
|
256
581
|
|
|
257
582
|
// wet asphalt: a warm-grey base in patchwork pours, two-scale aggregate
|
|
258
|
-
// grit, oily wear stains
|
|
259
|
-
//
|
|
583
|
+
// grit, oily wear stains and low-frequency wet patches that turn glossy and
|
|
584
|
+
// mirror the sky. detail fades in as the camera nears.
|
|
260
585
|
|
|
261
586
|
const p = positionWorld;
|
|
262
|
-
const
|
|
587
|
+
const dist = p.distance( cameraPosition );
|
|
588
|
+
const detail = smoothstep( 240, 25, dist );
|
|
589
|
+
const microFade = smoothstep( 22, 4, dist ); // the finest grit only resolves right under the camera, so fade it out fast to avoid shimmer
|
|
263
590
|
|
|
264
591
|
const blotch = mx_fractal_noise_float( p.mul( 0.2 ), 3 ).mul( 0.5 ).add( 0.5 );
|
|
265
592
|
|
|
266
|
-
// close-range detail — aggregate grit, oily wear pools
|
|
267
|
-
//
|
|
268
|
-
//
|
|
593
|
+
// close-range detail — aggregate grit, oily wear pools and worn paint — only
|
|
594
|
+
// resolves near the camera, so its noise is sampled ( inside the branch ) only
|
|
595
|
+
// where detail is non-zero and skipped across the far majority of the road
|
|
269
596
|
const near = Fn( () => {
|
|
270
597
|
|
|
271
598
|
const grit = float( 0 ).toVar(); // two scales of aggregate, -1..1
|
|
272
599
|
const stain = float( 0 ).toVar(); // oily wear pools
|
|
273
|
-
const crack = float( 0 ).toVar();
|
|
274
600
|
const worn = float( 1 ).toVar(); // paint rubbed thin and patchy, more so where tyres cross it
|
|
601
|
+
const micro = float( 0 ).toVar(); // fine, high-frequency grain for the close-up bump
|
|
275
602
|
|
|
276
603
|
If( detail.greaterThan( 0 ), () => {
|
|
277
604
|
|
|
278
605
|
grit.assign( mx_noise_float( p.mul( 7 ) ).add( mx_noise_float( p.mul( 23 ) ) ).mul( 0.5 ) );
|
|
279
606
|
stain.assign( smoothstep( 0.5, 0.85, mx_fractal_noise_float( p.mul( 0.45 ), 3 ).mul( 0.5 ).add( 0.5 ) ) );
|
|
280
|
-
crack.assign( smoothstep( 0.88, 1, mx_fractal_noise_float( p.mul( 1.1 ), 4 ).abs().oneMinus() ).mul( detail ) );
|
|
281
607
|
worn.assign( smoothstep( 0.25, 0.7, mx_fractal_noise_float( p.mul( 0.7 ), 3 ).mul( 0.5 ).add( 0.5 ) ).mul( 0.55 ).add( 0.35 ) );
|
|
282
608
|
|
|
283
609
|
} );
|
|
284
610
|
|
|
285
|
-
|
|
611
|
+
If( microFade.greaterThan( 0 ), () => {
|
|
612
|
+
|
|
613
|
+
micro.assign( mx_noise_float( p.mul( 45 ) ).mul( 0.6 ).add( mx_noise_float( p.mul( 80 ) ).mul( 0.4 ) ) );
|
|
614
|
+
|
|
615
|
+
} );
|
|
616
|
+
|
|
617
|
+
return vec4( grit, stain, worn, micro );
|
|
286
618
|
|
|
287
619
|
} )();
|
|
288
620
|
|
|
289
621
|
const grit = near.x;
|
|
290
622
|
const stain = near.y;
|
|
291
|
-
const
|
|
292
|
-
const
|
|
623
|
+
const worn = near.z;
|
|
624
|
+
const micro = near.w;
|
|
293
625
|
|
|
294
626
|
const base = mix( color( 0x24262b ), color( 0x3b3f46 ), blotch );
|
|
295
627
|
const gritty = base.mul( grit.mul( 0.22 ).mul( detail ).add( 1 ) );
|
|
@@ -334,10 +666,10 @@ function createRoadMaterial( layout ) {
|
|
|
334
666
|
const paint = laneV.max( laneH ).max( crossV ).max( crossH ).mul( detail ).mul( worn );
|
|
335
667
|
|
|
336
668
|
const material = new MeshStandardNodeMaterial();
|
|
337
|
-
const surface = mix( asphalt, asphalt.mul( 0.6 ), wet )
|
|
669
|
+
const surface = mix( asphalt, asphalt.mul( 0.6 ), wet );
|
|
338
670
|
material.colorNode = mix( surface, color( 0xd0ccc0 ), paint ); // worn white paint
|
|
339
671
|
material.roughnessNode = mix( float( 0.95 ).sub( paint.mul( 0.2 ) ), float( 0.32 ), wet );
|
|
340
|
-
material.normalNode = bumpNormal( grit.mul( 0.003 ).
|
|
672
|
+
material.normalNode = bumpNormal( grit.mul( 0.003 ).mul( detail ).add( micro.mul( 0.0016 ).mul( microFade ) ) ); // world units: ~3 mm aggregate, ~1.6 mm fine grain up close
|
|
341
673
|
|
|
342
674
|
return material;
|
|
343
675
|
|
|
@@ -15,18 +15,12 @@ import { ImprovedNoise } from '../math/ImprovedNoise.js';
|
|
|
15
15
|
import { mergeVertices } from '../utils/BufferGeometryUtils.js';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* Carpets a {@link TerrainGenerator}
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* Carpets a {@link TerrainGenerator} with trees in a single instanced draw call.
|
|
19
|
+
* Each tree is a distorted icosphere with a baked crown gradient. Altitude, slope
|
|
20
|
+
* and a density mask control placement; rotation and scale vary between trees.
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* dark-base / bright-top gradient. Tens of triangles each, so a single
|
|
25
|
-
* {@link THREE.InstancedMesh} of half a million of them costs one draw call. Trees
|
|
26
|
-
* are placed by rejection sampling against ecological rules — a min/max altitude
|
|
27
|
-
* band ( above the mist floor, below the snowline ), a slope limit ( none on
|
|
28
|
-
* cliffs ) and a low-frequency density mask that opens clearings — then jittered in
|
|
29
|
-
* yaw, lean and ( squared-biased ) scale so the stand never reads as copies.
|
|
22
|
+
* Compatible terrain objects expose `sampleHeight`, `sampleSlope`, `minY`, `maxY`
|
|
23
|
+
* and `parameters.size`.
|
|
30
24
|
*
|
|
31
25
|
* ```js
|
|
32
26
|
* const forest = new ForestGenerator( { count: 500000 } );
|
|
@@ -154,7 +148,13 @@ class ForestGenerator {
|
|
|
154
148
|
|
|
155
149
|
dispose() {
|
|
156
150
|
|
|
157
|
-
if ( this.mesh )
|
|
151
|
+
if ( this.mesh ) {
|
|
152
|
+
|
|
153
|
+
this.mesh.dispose();
|
|
154
|
+
this.mesh.geometry.dispose();
|
|
155
|
+
|
|
156
|
+
}
|
|
157
|
+
|
|
158
158
|
this.mesh = null;
|
|
159
159
|
this.group = null;
|
|
160
160
|
|