@lampdotdev/lamp 0.0.0-stage → 0.35.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/LICENSE +21 -0
- package/README.md +357 -2
- package/Resources/Devices/roku.json +410 -0
- package/Resources/Devices/xbox-one.json +367 -0
- package/Resources/GameKit/NOTICE.md +63 -0
- package/Resources/GameKit/apple/LampPage.swift +1646 -0
- package/Resources/GameKit/apple/LampPlayer.swift +46 -0
- package/Resources/GameKit/apple/LampWebApp.swift +63 -0
- package/Resources/GameKit/apple/LampWebGame.swift +87 -0
- package/Resources/GameKit/apple/Native.swift +12 -0
- package/Resources/GameKit/build.sh +55 -0
- package/Resources/GameKit/lamp_game.h +116 -0
- package/Resources/GameKit/lamp_host.h +19 -0
- package/Resources/GameKit/lamp_kit.cpp +61 -0
- package/Resources/GameKit/lamp_sound.cpp +455 -0
- package/Resources/GameKit/lamp_xbox.cpp +374 -0
- package/Resources/GameKit/libraries/HandmadeMath.h +3940 -0
- package/Resources/GameKit/libraries/cgltf.h +7240 -0
- package/Resources/GameKit/libraries/dr_mp3.h +5430 -0
- package/Resources/GameKit/libraries/dr_wav.h +9209 -0
- package/Resources/GameKit/libraries/sokol_debugtext.h +4754 -0
- package/Resources/GameKit/libraries/sokol_gfx.h +29558 -0
- package/Resources/GameKit/libraries/sokol_gl.h +4538 -0
- package/Resources/GameKit/libraries/sokol_log.h +335 -0
- package/Resources/GameKit/libraries/sokol_shape.h +1531 -0
- package/Resources/GameKit/libraries/stb_image.h +7988 -0
- package/Resources/GameKit/libraries/stb_vorbis.c +5584 -0
- package/Resources/GameKit/scaffold/Game/game.cpp +142 -0
- package/Resources/GameKit/scaffold/Game/scene.glsl +49 -0
- package/Resources/GameKit/scaffold-web/Web/game.js +31 -0
- package/Resources/GameKit/scaffold-web/Web/index.html +13 -0
- package/Resources/GameKit/scaffold-web/Web/making.js +33 -0
- package/Resources/GameKit/scaffold-web/Web/world.js +33 -0
- package/Resources/GameKit/web/lamp-game.js +3036 -0
- package/Resources/GameKit/web/lamp-phaser.js +128 -0
- package/Resources/WebHost/App.exe +0 -0
- package/Resources/WebHost/Microsoft.Web.WebView2.Core.dll +0 -0
- package/Resources/WebHost/WebView2-LICENSE.txt +27 -0
- package/Resources/WebHost/lamp_controllers.h +1506 -0
- package/Resources/WebHost/lamp_web_host.cpp +1173 -0
- package/Resources/WebLibraries/earlier.txt +318 -0
- package/Resources/WebLibraries/phaser/LICENSE.md +20 -0
- package/Resources/WebLibraries/phaser/NOTICE.md +2 -0
- package/Resources/WebLibraries/phaser/phaser.esm.min.js +1 -0
- package/Resources/WebLibraries/qrcode/LICENSE +21 -0
- package/Resources/WebLibraries/qrcode/NOTICE.md +4 -0
- package/Resources/WebLibraries/qrcode/qrcode.js +2297 -0
- package/Resources/WebLibraries/rapier/LICENSE +201 -0
- package/Resources/WebLibraries/rapier/NOTICE.md +3 -0
- package/Resources/WebLibraries/rapier/rapier.js +2 -0
- package/Resources/WebLibraries/three/LICENSE +21 -0
- package/Resources/WebLibraries/three/NOTICE.md +4 -0
- package/Resources/WebLibraries/three/addons/animation/AnimationClipCreator.js +168 -0
- package/Resources/WebLibraries/three/addons/animation/CCDIKSolver.js +607 -0
- package/Resources/WebLibraries/three/addons/controls/ArcballControls.js +3543 -0
- package/Resources/WebLibraries/three/addons/controls/DragControls.js +452 -0
- package/Resources/WebLibraries/three/addons/controls/FirstPersonControls.js +512 -0
- package/Resources/WebLibraries/three/addons/controls/FlyControls.js +384 -0
- package/Resources/WebLibraries/three/addons/controls/MapControls.js +116 -0
- package/Resources/WebLibraries/three/addons/controls/OrbitControls.js +1985 -0
- package/Resources/WebLibraries/three/addons/controls/PointerLockControls.js +264 -0
- package/Resources/WebLibraries/three/addons/controls/TrackballControls.js +1106 -0
- package/Resources/WebLibraries/three/addons/controls/TransformControls.js +2003 -0
- package/Resources/WebLibraries/three/addons/curves/CurveExtras.js +694 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSCurve.js +169 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSSurface.js +98 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSUtils.js +532 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSVolume.js +82 -0
- package/Resources/WebLibraries/three/addons/effects/AnaglyphEffect.js +274 -0
- package/Resources/WebLibraries/three/addons/effects/AsciiEffect.js +323 -0
- package/Resources/WebLibraries/three/addons/effects/OutlineEffect.js +489 -0
- package/Resources/WebLibraries/three/addons/effects/ParallaxBarrierEffect.js +155 -0
- package/Resources/WebLibraries/three/addons/effects/StereoEffect.js +91 -0
- package/Resources/WebLibraries/three/addons/environments/ColorEnvironment.js +59 -0
- package/Resources/WebLibraries/three/addons/environments/DebugEnvironment.js +102 -0
- package/Resources/WebLibraries/three/addons/environments/RoomEnvironment.js +185 -0
- package/Resources/WebLibraries/three/addons/geometries/BoxLineGeometry.js +92 -0
- package/Resources/WebLibraries/three/addons/geometries/ConvexGeometry.js +72 -0
- package/Resources/WebLibraries/three/addons/geometries/DecalGeometry.js +420 -0
- package/Resources/WebLibraries/three/addons/geometries/LoftGeometry.js +355 -0
- package/Resources/WebLibraries/three/addons/geometries/ParametricFunctions.js +100 -0
- package/Resources/WebLibraries/three/addons/geometries/ParametricGeometry.js +172 -0
- package/Resources/WebLibraries/three/addons/geometries/RoundedBoxGeometry.js +216 -0
- package/Resources/WebLibraries/three/addons/geometries/TeapotGeometry.js +689 -0
- package/Resources/WebLibraries/three/addons/geometries/TextGeometry.js +102 -0
- package/Resources/WebLibraries/three/addons/helpers/AnimationPathHelper.js +302 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelper.js +166 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelperWebGL.js +221 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeHelper.js +166 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeHelperGPU.js +102 -0
- package/Resources/WebLibraries/three/addons/helpers/OctreeHelper.js +109 -0
- package/Resources/WebLibraries/three/addons/helpers/PositionalAudioHelper.js +169 -0
- package/Resources/WebLibraries/three/addons/helpers/RapierHelper.js +59 -0
- package/Resources/WebLibraries/three/addons/helpers/RectAreaLightHelper.js +118 -0
- package/Resources/WebLibraries/three/addons/helpers/TextureHelper.js +265 -0
- package/Resources/WebLibraries/three/addons/helpers/TextureHelperGPU.js +214 -0
- package/Resources/WebLibraries/three/addons/helpers/VertexNormalsHelper.js +155 -0
- package/Resources/WebLibraries/three/addons/helpers/VertexTangentsHelper.js +133 -0
- package/Resources/WebLibraries/three/addons/helpers/ViewHelper.js +529 -0
- package/Resources/WebLibraries/three/addons/interactive/HTMLMesh.js +617 -0
- package/Resources/WebLibraries/three/addons/interactive/InteractiveGroup.js +224 -0
- package/Resources/WebLibraries/three/addons/interactive/SelectionBox.js +324 -0
- package/Resources/WebLibraries/three/addons/interactive/SelectionHelper.js +150 -0
- package/Resources/WebLibraries/three/addons/libs/fflate.module.js +2699 -0
- package/Resources/WebLibraries/three/addons/libs/lil-gui.module.min.js +8 -0
- package/Resources/WebLibraries/three/addons/libs/meshopt_decoder.module.js +196 -0
- package/Resources/WebLibraries/three/addons/libs/potpack.module.js +125 -0
- package/Resources/WebLibraries/three/addons/libs/stats.module.js +167 -0
- package/Resources/WebLibraries/three/addons/libs/tween.module.js +876 -0
- package/Resources/WebLibraries/three/addons/lighting/ClusteredLighting.js +153 -0
- package/Resources/WebLibraries/three/addons/lighting/DynamicLighting.js +82 -0
- package/Resources/WebLibraries/three/addons/lighting/LightMapper.js +295 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGrid.js +923 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGridUtils.js +107 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGridWebGL.js +846 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIConeTracer.js +243 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIIrradiance.js +43 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGINode.js +617 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGISceneCollector.js +793 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIVolume.js +1440 -0
- package/Resources/WebLibraries/three/addons/lights/LightProbeGenerator.js +337 -0
- package/Resources/WebLibraries/three/addons/lights/RectAreaLightTexturesLib.js +127 -0
- package/Resources/WebLibraries/three/addons/lights/RectAreaLightUniformsLib.js +40 -0
- package/Resources/WebLibraries/three/addons/lights/SunLight.js +100 -0
- package/Resources/WebLibraries/three/addons/lights/SunLightNode.js +56 -0
- package/Resources/WebLibraries/three/addons/lights/SunLightShadow.js +319 -0
- package/Resources/WebLibraries/three/addons/lights/SunShadowNode.js +312 -0
- package/Resources/WebLibraries/three/addons/lines/Line2.js +56 -0
- package/Resources/WebLibraries/three/addons/lines/LineGeometry.js +157 -0
- package/Resources/WebLibraries/three/addons/lines/LineMaterial.js +742 -0
- package/Resources/WebLibraries/three/addons/lines/LineSegments2.js +434 -0
- package/Resources/WebLibraries/three/addons/lines/LineSegmentsGeometry.js +298 -0
- package/Resources/WebLibraries/three/addons/lines/Wireframe.js +108 -0
- package/Resources/WebLibraries/three/addons/lines/WireframeGeometry2.js +49 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/Line2.js +46 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/LineSegments2.js +419 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/Wireframe.js +86 -0
- package/Resources/WebLibraries/three/addons/loaders/EXRLoader.js +3411 -0
- package/Resources/WebLibraries/three/addons/loaders/FBXLoader.js +4660 -0
- package/Resources/WebLibraries/three/addons/loaders/FontLoader.js +262 -0
- package/Resources/WebLibraries/three/addons/loaders/GLTFLoader.js +5006 -0
- package/Resources/WebLibraries/three/addons/loaders/HDRLoader.js +463 -0
- package/Resources/WebLibraries/three/addons/loaders/MTLLoader.js +601 -0
- package/Resources/WebLibraries/three/addons/loaders/OBJLoader.js +961 -0
- package/Resources/WebLibraries/three/addons/loaders/PLYLoader.js +992 -0
- package/Resources/WebLibraries/three/addons/loaders/RGBELoader.js +18 -0
- package/Resources/WebLibraries/three/addons/loaders/STLLoader.js +423 -0
- package/Resources/WebLibraries/three/addons/loaders/SVGLoader.js +3297 -0
- package/Resources/WebLibraries/three/addons/loaders/TGALoader.js +539 -0
- package/Resources/WebLibraries/three/addons/loaders/UltraHDRLoader.js +757 -0
- package/Resources/WebLibraries/three/addons/math/Capsule.js +159 -0
- package/Resources/WebLibraries/three/addons/math/ColorConverter.js +62 -0
- package/Resources/WebLibraries/three/addons/math/ColorSpaces.js +147 -0
- package/Resources/WebLibraries/three/addons/math/ConvexHull.js +1695 -0
- package/Resources/WebLibraries/three/addons/math/ImprovedNoise.js +88 -0
- package/Resources/WebLibraries/three/addons/math/Lut.js +317 -0
- package/Resources/WebLibraries/three/addons/math/MeshSurfaceSampler.js +315 -0
- package/Resources/WebLibraries/three/addons/math/OBB.js +535 -0
- package/Resources/WebLibraries/three/addons/math/Octree.js +825 -0
- package/Resources/WebLibraries/three/addons/math/SimplexNoise.js +470 -0
- package/Resources/WebLibraries/three/addons/misc/ConvexObjectBreaker.js +539 -0
- package/Resources/WebLibraries/three/addons/misc/GPUComputationRenderer.js +508 -0
- package/Resources/WebLibraries/three/addons/misc/Gyroscope.js +78 -0
- package/Resources/WebLibraries/three/addons/misc/MorphAnimMesh.js +119 -0
- package/Resources/WebLibraries/three/addons/misc/MorphBlendMesh.js +425 -0
- package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMap.js +370 -0
- package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMapGPU.js +322 -0
- package/Resources/WebLibraries/three/addons/misc/RollerCoaster.js +661 -0
- package/Resources/WebLibraries/three/addons/misc/Sculptor.js +1679 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorMesh.js +1504 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorTools.js +1180 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorUtils.js +345 -0
- package/Resources/WebLibraries/three/addons/misc/TileCreasedNormalsPlugin.js +270 -0
- package/Resources/WebLibraries/three/addons/misc/TubePainter.js +611 -0
- package/Resources/WebLibraries/three/addons/misc/Volume.js +520 -0
- package/Resources/WebLibraries/three/addons/misc/VolumeSlice.js +275 -0
- package/Resources/WebLibraries/three/addons/modifiers/CurveModifier.js +374 -0
- package/Resources/WebLibraries/three/addons/modifiers/CurveModifierGPU.js +256 -0
- package/Resources/WebLibraries/three/addons/modifiers/EdgeSplitModifier.js +299 -0
- package/Resources/WebLibraries/three/addons/modifiers/TessellateModifier.js +340 -0
- package/Resources/WebLibraries/three/addons/objects/GroundedSkybox.js +69 -0
- package/Resources/WebLibraries/three/addons/objects/Lensflare.js +489 -0
- package/Resources/WebLibraries/three/addons/objects/LensflareMesh.js +376 -0
- package/Resources/WebLibraries/three/addons/objects/MarchingCubes.js +1261 -0
- package/Resources/WebLibraries/three/addons/objects/Reflector.js +390 -0
- package/Resources/WebLibraries/three/addons/objects/ReflectorForSSRPass.js +393 -0
- package/Resources/WebLibraries/three/addons/objects/Refractor.js +389 -0
- package/Resources/WebLibraries/three/addons/objects/ShadowMesh.js +130 -0
- package/Resources/WebLibraries/three/addons/objects/Sky.js +342 -0
- package/Resources/WebLibraries/three/addons/objects/SkyMesh.js +403 -0
- package/Resources/WebLibraries/three/addons/objects/Water.js +374 -0
- package/Resources/WebLibraries/three/addons/objects/Water2.js +403 -0
- package/Resources/WebLibraries/three/addons/objects/Water2Mesh.js +199 -0
- package/Resources/WebLibraries/three/addons/objects/WaterMesh.js +194 -0
- package/Resources/WebLibraries/three/addons/postprocessing/AfterimagePass.js +187 -0
- package/Resources/WebLibraries/three/addons/postprocessing/BloomPass.js +274 -0
- package/Resources/WebLibraries/three/addons/postprocessing/BokehPass.js +218 -0
- package/Resources/WebLibraries/three/addons/postprocessing/ClearPass.js +97 -0
- package/Resources/WebLibraries/three/addons/postprocessing/CubeTexturePass.js +146 -0
- package/Resources/WebLibraries/three/addons/postprocessing/DotScreenPass.js +114 -0
- package/Resources/WebLibraries/three/addons/postprocessing/EffectComposer.js +365 -0
- package/Resources/WebLibraries/three/addons/postprocessing/FXAAPass.js +40 -0
- package/Resources/WebLibraries/three/addons/postprocessing/FilmPass.js +113 -0
- package/Resources/WebLibraries/three/addons/postprocessing/GTAOPass.js +735 -0
- package/Resources/WebLibraries/three/addons/postprocessing/GlitchPass.js +177 -0
- package/Resources/WebLibraries/three/addons/postprocessing/HalftonePass.js +134 -0
- package/Resources/WebLibraries/three/addons/postprocessing/LUTPass.js +138 -0
- package/Resources/WebLibraries/three/addons/postprocessing/MaskPass.js +195 -0
- package/Resources/WebLibraries/three/addons/postprocessing/OutlinePass.js +776 -0
- package/Resources/WebLibraries/three/addons/postprocessing/OutputPass.js +148 -0
- package/Resources/WebLibraries/three/addons/postprocessing/Pass.js +191 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderPass.js +193 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderPixelatedPass.js +314 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderTransitionPass.js +267 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SAOPass.js +407 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SMAAPass.js +230 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSAARenderPass.js +313 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSAOPass.js +527 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSRPass.js +858 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SavePass.js +132 -0
- package/Resources/WebLibraries/three/addons/postprocessing/ShaderPass.js +135 -0
- package/Resources/WebLibraries/three/addons/postprocessing/TAARenderPass.js +243 -0
- package/Resources/WebLibraries/three/addons/postprocessing/TexturePass.js +131 -0
- package/Resources/WebLibraries/three/addons/postprocessing/UnrealBloomPass.js +541 -0
- package/Resources/WebLibraries/three/addons/shaders/ACESFilmicToneMappingShader.js +96 -0
- package/Resources/WebLibraries/three/addons/shaders/AfterimageShader.js +63 -0
- package/Resources/WebLibraries/three/addons/shaders/BasicShader.js +36 -0
- package/Resources/WebLibraries/three/addons/shaders/BleachBypassShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/BlendShader.js +56 -0
- package/Resources/WebLibraries/three/addons/shaders/BokehShader.js +151 -0
- package/Resources/WebLibraries/three/addons/shaders/BokehShader2.js +404 -0
- package/Resources/WebLibraries/three/addons/shaders/BrightnessContrastShader.js +62 -0
- package/Resources/WebLibraries/three/addons/shaders/ColorCorrectionShader.js +59 -0
- package/Resources/WebLibraries/three/addons/shaders/ColorifyShader.js +57 -0
- package/Resources/WebLibraries/three/addons/shaders/ConvolutionShader.js +74 -0
- package/Resources/WebLibraries/three/addons/shaders/CopyShader.js +52 -0
- package/Resources/WebLibraries/three/addons/shaders/DOFMipMapShader.js +63 -0
- package/Resources/WebLibraries/three/addons/shaders/DepthLimitedBlurShader.js +183 -0
- package/Resources/WebLibraries/three/addons/shaders/DigitalGlitch.js +104 -0
- package/Resources/WebLibraries/three/addons/shaders/DotScreenShader.js +75 -0
- package/Resources/WebLibraries/three/addons/shaders/ExposureShader.js +51 -0
- package/Resources/WebLibraries/three/addons/shaders/FXAAShader.js +298 -0
- package/Resources/WebLibraries/three/addons/shaders/FilmShader.js +73 -0
- package/Resources/WebLibraries/three/addons/shaders/FocusShader.js +94 -0
- package/Resources/WebLibraries/three/addons/shaders/FreiChenShader.js +103 -0
- package/Resources/WebLibraries/three/addons/shaders/GTAOShader.js +437 -0
- package/Resources/WebLibraries/three/addons/shaders/GammaCorrectionShader.js +52 -0
- package/Resources/WebLibraries/three/addons/shaders/HalftoneShader.js +332 -0
- package/Resources/WebLibraries/three/addons/shaders/HorizontalBlurShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/HorizontalTiltShiftShader.js +70 -0
- package/Resources/WebLibraries/three/addons/shaders/HueSaturationShader.js +74 -0
- package/Resources/WebLibraries/three/addons/shaders/KaleidoShader.js +65 -0
- package/Resources/WebLibraries/three/addons/shaders/LuminosityHighPassShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/LuminosityShader.js +54 -0
- package/Resources/WebLibraries/three/addons/shaders/MirrorShader.js +62 -0
- package/Resources/WebLibraries/three/addons/shaders/NormalMapShader.js +60 -0
- package/Resources/WebLibraries/three/addons/shaders/OutputShader.js +103 -0
- package/Resources/WebLibraries/three/addons/shaders/PoissonDenoiseShader.js +230 -0
- package/Resources/WebLibraries/three/addons/shaders/RGBShiftShader.js +61 -0
- package/Resources/WebLibraries/three/addons/shaders/SAOShader.js +201 -0
- package/Resources/WebLibraries/three/addons/shaders/SMAAShader.js +489 -0
- package/Resources/WebLibraries/three/addons/shaders/SSAOShader.js +331 -0
- package/Resources/WebLibraries/three/addons/shaders/SSRShader.js +396 -0
- package/Resources/WebLibraries/three/addons/shaders/SepiaShader.js +57 -0
- package/Resources/WebLibraries/three/addons/shaders/SobelOperatorShader.js +98 -0
- package/Resources/WebLibraries/three/addons/shaders/SubsurfaceScatteringShader.js +95 -0
- package/Resources/WebLibraries/three/addons/shaders/TechnicolorShader.js +51 -0
- package/Resources/WebLibraries/three/addons/shaders/ToonShader.js +349 -0
- package/Resources/WebLibraries/three/addons/shaders/TriangleBlurShader.js +79 -0
- package/Resources/WebLibraries/three/addons/shaders/UnpackDepthRGBAShader.js +60 -0
- package/Resources/WebLibraries/three/addons/shaders/VelocityShader.js +137 -0
- package/Resources/WebLibraries/three/addons/shaders/VerticalBlurShader.js +66 -0
- package/Resources/WebLibraries/three/addons/shaders/VerticalTiltShiftShader.js +70 -0
- package/Resources/WebLibraries/three/addons/shaders/VignetteShader.js +56 -0
- package/Resources/WebLibraries/three/addons/shaders/VolumeShader.js +285 -0
- package/Resources/WebLibraries/three/addons/shaders/WaterRefractionShader.js +106 -0
- package/Resources/WebLibraries/three/addons/textures/FlakesTexture.js +54 -0
- package/Resources/WebLibraries/three/addons/tsl/WebGLNodesHandler.js +607 -0
- package/Resources/WebLibraries/three/addons/tsl/display/AfterImageNode.js +256 -0
- package/Resources/WebLibraries/three/addons/tsl/display/AnaglyphPassNode.js +550 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BilateralBlurNode.js +377 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BleachBypass.js +33 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BloomNode.js +599 -0
- package/Resources/WebLibraries/three/addons/tsl/display/CRT.js +150 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ChromaticAberrationNode.js +163 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DenoiseNode.js +354 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DepthOfFieldNode.js +572 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DotScreenNode.js +104 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FSR1Node.js +481 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FXAANode.js +357 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FilmNode.js +101 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GTAONode.js +727 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GaussianBlurNode.js +412 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GodraysNode.js +604 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ImportanceSampledEnvironment.js +564 -0
- package/Resources/WebLibraries/three/addons/tsl/display/LensflareNode.js +282 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Lut3DNode.js +109 -0
- package/Resources/WebLibraries/three/addons/tsl/display/MotionBlur.js +33 -0
- package/Resources/WebLibraries/three/addons/tsl/display/OITPassNode.js +341 -0
- package/Resources/WebLibraries/three/addons/tsl/display/OutlineNode.js +916 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ParallaxBarrierPassNode.js +90 -0
- package/Resources/WebLibraries/three/addons/tsl/display/PixelationPassNode.js +227 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RGBShiftNode.js +96 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RecurrentDenoiseNode.js +812 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RetroPassNode.js +263 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SMAANode.js +729 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSAAPassNode.js +344 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSAONode.js +422 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSGINode.js +698 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSRNode.js +1430 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSSNode.js +479 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Sepia.js +24 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Shape.js +29 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SharpenNode.js +284 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SobelOperatorNode.js +168 -0
- package/Resources/WebLibraries/three/addons/tsl/display/StereoCompositePassNode.js +190 -0
- package/Resources/WebLibraries/three/addons/tsl/display/StereoPassNode.js +117 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TAAUNode.js +700 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TRAANode.js +609 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TemporalReprojectNode.js +1024 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TransitionNode.js +141 -0
- package/Resources/WebLibraries/three/addons/tsl/display/boxBlur.js +65 -0
- package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlend.js +80 -0
- package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlur.js +63 -0
- package/Resources/WebLibraries/three/addons/tsl/display/hashBlur.js +55 -0
- package/Resources/WebLibraries/three/addons/tsl/display/lensDirt.js +30 -0
- package/Resources/WebLibraries/three/addons/tsl/display/radialBlur.js +68 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/ClusteredLightsNode.js +994 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/DynamicLightsNode.js +201 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/LightProbeGridNode.js +183 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/AmbientLightDataNode.js +67 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/DirectionalLightDataNode.js +117 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/HemisphereLightDataNode.js +105 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/PointLightDataNode.js +140 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/SpotLightDataNode.js +167 -0
- package/Resources/WebLibraries/three/addons/tsl/math/Bayer.js +84 -0
- package/Resources/WebLibraries/three/addons/tsl/math/curlNoise.js +107 -0
- package/Resources/WebLibraries/three/addons/tsl/math/voronoiNoise.js +112 -0
- package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNode.js +542 -0
- package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNodeHelper.js +212 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/GroundedSkybox.js +62 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/RNoise.js +51 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/Raymarching.js +70 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/SoftParticles.js +53 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/SpecularHelpers.js +302 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/TAAUtils.js +184 -0
- package/Resources/WebLibraries/three/addons/utils/BufferGeometryUtils.js +1523 -0
- package/Resources/WebLibraries/three/addons/utils/CameraUtils.js +82 -0
- package/Resources/WebLibraries/three/addons/utils/ColorUtils.js +76 -0
- package/Resources/WebLibraries/three/addons/utils/GaussianSplatUtils.js +229 -0
- package/Resources/WebLibraries/three/addons/utils/GeometryCompressionUtils.js +547 -0
- package/Resources/WebLibraries/three/addons/utils/GeometryUtils.js +226 -0
- package/Resources/WebLibraries/three/addons/utils/LDrawUtils.js +211 -0
- package/Resources/WebLibraries/three/addons/utils/SceneOptimizer.js +459 -0
- package/Resources/WebLibraries/three/addons/utils/SceneUtils.js +363 -0
- package/Resources/WebLibraries/three/addons/utils/ShadowMapViewer.js +244 -0
- package/Resources/WebLibraries/three/addons/utils/ShadowMapViewerGPU.js +233 -0
- package/Resources/WebLibraries/three/addons/utils/SkeletonUtils.js +496 -0
- package/Resources/WebLibraries/three/addons/utils/SortUtils.js +175 -0
- package/Resources/WebLibraries/three/addons/utils/UVsDebug.js +173 -0
- package/Resources/WebLibraries/three/addons/utils/WebGLTextureUtils.js +115 -0
- package/Resources/WebLibraries/three/addons/utils/WebGPUTextureUtils.js +81 -0
- package/Resources/WebLibraries/three/addons/utils/WorkerPool.js +167 -0
- package/Resources/WebLibraries/three/addons/utils/unwrapUVs.js +865 -0
- package/Resources/WebLibraries/three/three.core.js +61162 -0
- package/Resources/WebLibraries/three/three.module.js +19537 -0
- package/Resources/WebLibraries/three/three.tsl.js +41903 -0
- package/Resources/WebLibraries/three/three.webgpu.js +53714 -0
- package/Resources/skills/2d-game/SKILL.md +305 -0
- package/Resources/skills/3d-game/SKILL.md +274 -0
- package/Resources/skills/accounts/SKILL.md +41 -0
- package/Resources/skills/android-design/SKILL.md +159 -0
- package/Resources/skills/app-ai/SKILL.md +154 -0
- package/Resources/skills/app-intents/SKILL.md +31 -0
- package/Resources/skills/app-kinds/SKILL.md +122 -0
- package/Resources/skills/apple-watch/SKILL.md +43 -0
- package/Resources/skills/assets/SKILL.md +183 -0
- package/Resources/skills/building-blocks/SKILL.md +97 -0
- package/Resources/skills/device-control/SKILL.md +56 -0
- package/Resources/skills/device-integrations/SKILL.md +278 -0
- package/Resources/skills/finder-files/SKILL.md +19 -0
- package/Resources/skills/game/SKILL.md +414 -0
- package/Resources/skills/game-3d/SKILL.md +12 -0
- package/Resources/skills/game-art/SKILL.md +11 -0
- package/Resources/skills/game-feel/SKILL.md +13 -0
- package/Resources/skills/game-levels/SKILL.md +12 -0
- package/Resources/skills/game-live/SKILL.md +12 -0
- package/Resources/skills/game-physics/SKILL.md +13 -0
- package/Resources/skills/game-playtest/SKILL.md +26 -0
- package/Resources/skills/game-ui/SKILL.md +278 -0
- package/Resources/skills/github-projects/SKILL.md +59 -0
- package/Resources/skills/icloud-sync/SKILL.md +30 -0
- package/Resources/skills/iphone-hardware/SKILL.md +57 -0
- package/Resources/skills/iphone-widgets/SKILL.md +53 -0
- package/Resources/skills/lg-developer-mode/SKILL.md +152 -0
- package/Resources/skills/mac-widgets/SKILL.md +60 -0
- package/Resources/skills/maps/SKILL.md +8 -0
- package/Resources/skills/menu-bar/SKILL.md +36 -0
- package/Resources/skills/more-apps/SKILL.md +53 -0
- package/Resources/skills/phone-controllers/SKILL.md +79 -0
- package/Resources/skills/phone-pages/SKILL.md +173 -0
- package/Resources/skills/roku-developer-mode/SKILL.md +106 -0
- package/Resources/skills/scene-3d/SKILL.md +27 -0
- package/Resources/skills/scripting/SKILL.md +17 -0
- package/Resources/skills/share-extension/SKILL.md +22 -0
- package/Resources/skills/tv-design/SKILL.md +72 -0
- package/Resources/skills/web-app/SKILL.md +136 -0
- package/Resources/skills/web-game/SKILL.md +95 -0
- package/Resources/skills/web-or-native/SKILL.md +103 -0
- package/Resources/skills/wish-links/SKILL.md +156 -0
- package/THIRD_PARTY_NOTICES.md +170 -0
- package/cli/android.mjs +941 -0
- package/cli/browser.mjs +268 -0
- package/cli/calls.mjs +390 -0
- package/cli/dev.mjs +773 -0
- package/cli/devices.mjs +984 -0
- package/cli/lamp.mjs +1016 -0
- package/cli/lampapp.mjs +332 -0
- package/cli/lamps/android-host/LampPageGateway.kt +345 -0
- package/cli/lamps/android-host/app/build.gradle.kts +40 -0
- package/cli/lamps/android-host/build.gradle.kts +4 -0
- package/cli/lamps/android-host/game/AndroidManifest.xml +33 -0
- package/cli/lamps/android-host/game/MainActivity.kt +173 -0
- package/cli/lamps/android-host/gradle/libs.versions.toml +39 -0
- package/cli/lamps/android-host/gradle.properties +8 -0
- package/cli/lamps/android-host/page/AndroidManifest.xml +35 -0
- package/cli/lamps/android-host/page/MainActivity.kt +193 -0
- package/cli/lamps/android-host/settings.gradle.kts +30 -0
- package/cli/lamps/android-host/tools.json +43 -0
- package/cli/lamps/lamp-controllers.js +2 -0
- package/cli/lamps/lamp-for-games.js +6863 -0
- package/cli/lamps/lamp.js +7023 -0
- package/cli/lamps/mac-starter/.lamp/meta.json +1 -0
- package/cli/lamps/mac-starter/APP.md +12 -0
- package/cli/lamps/mac-starter/Package.swift +8 -0
- package/cli/lamps/mac-starter/Sources/App.swift +11 -0
- package/cli/lamps/mac-starter/Sources/ContentView.swift +17 -0
- package/cli/lamps/mac-starter/Sources/LampSupport.swift +18097 -0
- package/cli/lamps/mac-starter/build.sh +336 -0
- package/cli/lamps/mac-starter/gitignore +3 -0
- package/cli/lamps/mac-starter/lamp-starter.json +6 -0
- package/cli/lamps/web-starter/APP.md +8 -0
- package/cli/lamps/web-starter/app.js +1 -0
- package/cli/lamps/web-starter/index.html +17 -0
- package/cli/lamps/web-starter/lamp-starter.json +5 -0
- package/cli/lamps/web-starter/lamp.js +7023 -0
- package/cli/lamps/web-starter/style.css +25 -0
- package/cli/link.mjs +138 -0
- package/cli/mac.mjs +621 -0
- package/cli/mdns.mjs +205 -0
- package/cli/msix.mjs +413 -0
- package/cli/network.mjs +209 -0
- package/cli/outside.mjs +140 -0
- package/cli/page.js +165 -0
- package/cli/place.mjs +298 -0
- package/cli/png.mjs +184 -0
- package/cli/share.mjs +202 -0
- package/cli/skill/SKILL.md +255 -0
- package/cli/skills.mjs +71 -0
- package/cli/state.mjs +173 -0
- package/cli/update.mjs +57 -0
- package/package.json +20 -4
- package/site/lib/quota.js +59 -0
- package/site/lib/shared-wishes.js +996 -0
|
@@ -0,0 +1,994 @@
|
|
|
1
|
+
import { DataTexture, FloatType, RGBAFormat, Vector2, Vector3, LightsNode, NodeUpdateType, NodeUtils, PointLightNode, SpotLightNode } from 'three/webgpu';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
instancedArray, nodeProxy, int, float, vec3, vec4, ivec2, ivec4, uniform, Break, Loop, positionView,
|
|
5
|
+
Fn, If, textureLoad, instanceIndex, screenCoordinate, directPointLight,
|
|
6
|
+
renderGroup,
|
|
7
|
+
min, max, pow, log, clamp, dot, smoothstep
|
|
8
|
+
} from 'three/tsl';
|
|
9
|
+
|
|
10
|
+
const _vector3 = /*@__PURE__*/ new Vector3();
|
|
11
|
+
const _direction = /*@__PURE__*/ new Vector3();
|
|
12
|
+
const _targetPosition = /*@__PURE__*/ new Vector3();
|
|
13
|
+
const _size = /*@__PURE__*/ new Vector2();
|
|
14
|
+
|
|
15
|
+
// light data texture rows
|
|
16
|
+
|
|
17
|
+
const POSITION_ROW = 0; // world position, cutoff distance
|
|
18
|
+
const COLOR_ROW = 1; // color * intensity, decay
|
|
19
|
+
const SPOT_ROW = 2; // scaled world spot direction, scaled cone cosine
|
|
20
|
+
const BOUNDS_ROW = 3; // world bounding sphere center, radius ( negative if unbounded )
|
|
21
|
+
const ROWS = 4;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A custom version of `LightsNode` implementing Forward+ clustered shading:
|
|
25
|
+
* the view frustum is subdivided into a 3D grid of clusters (X × Y screen tiles
|
|
26
|
+
* times an exponentially-spaced set of Z depth slices), and each cluster holds
|
|
27
|
+
* only the point and spot lights whose bounding spheres intersect it. At shading time each fragment
|
|
28
|
+
* looks up its cluster and loops over just that cluster's lights. Unlike 2D tiled
|
|
29
|
+
* lighting, clustered shading culls lights that share screen pixels but lie at
|
|
30
|
+
* different depths — suitable for 3D scenes with real depth complexity.
|
|
31
|
+
*
|
|
32
|
+
* @augments LightsNode
|
|
33
|
+
* @three_import import { clusteredLights } from 'three/addons/tsl/lighting/ClusteredLightsNode.js';
|
|
34
|
+
*/
|
|
35
|
+
class ClusteredLightsNode extends LightsNode {
|
|
36
|
+
|
|
37
|
+
static get type() {
|
|
38
|
+
|
|
39
|
+
return 'ClusteredLightsNode';
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Constructs a new clustered lights node.
|
|
45
|
+
*
|
|
46
|
+
* @param {number} [maxLights=1024] - Maximum number of point and spot lights.
|
|
47
|
+
* @param {number} [tileSize=32] - Screen tile size in pixels (cluster XY size).
|
|
48
|
+
* @param {number} [zSlices=24] - Number of exponential depth slices.
|
|
49
|
+
* @param {number} [maxLightsPerCluster=64] - Per-cluster light-list capacity.
|
|
50
|
+
*/
|
|
51
|
+
constructor( maxLights = 1024, tileSize = 32, zSlices = 24, maxLightsPerCluster = 64 ) {
|
|
52
|
+
|
|
53
|
+
super();
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* This flag can be used for type testing.
|
|
57
|
+
*
|
|
58
|
+
* @type {boolean}
|
|
59
|
+
* @readonly
|
|
60
|
+
* @default true
|
|
61
|
+
*/
|
|
62
|
+
this.isClusteredLightsNode = true;
|
|
63
|
+
|
|
64
|
+
this.materialLights = [];
|
|
65
|
+
this.clusteredLights = [];
|
|
66
|
+
|
|
67
|
+
this.maxLights = maxLights;
|
|
68
|
+
this.tileSize = tileSize;
|
|
69
|
+
this.zSlices = zSlices;
|
|
70
|
+
this.maxLightsPerCluster = maxLightsPerCluster;
|
|
71
|
+
|
|
72
|
+
this._chunksPerCluster = Math.ceil( maxLightsPerCluster / 4 );
|
|
73
|
+
|
|
74
|
+
this._bufferSize = null;
|
|
75
|
+
this._isWebGLBackend = false;
|
|
76
|
+
this._needsRebuild = false;
|
|
77
|
+
this._invocationsPerCluster = 1;
|
|
78
|
+
this._lightIndexes = null;
|
|
79
|
+
this._renderer = null;
|
|
80
|
+
this._screenClusterIndex = null;
|
|
81
|
+
this._compute = null;
|
|
82
|
+
|
|
83
|
+
const lightsData = new Float32Array( maxLights * 4 * ROWS );
|
|
84
|
+
this._lightsTexture = new DataTexture( lightsData, maxLights, ROWS, RGBAFormat, FloatType );
|
|
85
|
+
|
|
86
|
+
// Per Z-slice light range for Z-culling (CPU-sorted, uploaded each frame)
|
|
87
|
+
|
|
88
|
+
this._zSliceRangesData = new Float32Array( zSlices * 4 );
|
|
89
|
+
this._zSliceRangesTexture = new DataTexture( this._zSliceRangesData, zSlices, 1, RGBAFormat, FloatType );
|
|
90
|
+
|
|
91
|
+
this._lightViewZ = new Float32Array( maxLights );
|
|
92
|
+
this._lightSortOrder = [];
|
|
93
|
+
|
|
94
|
+
this._lightsCount = uniform( 0, 'int' );
|
|
95
|
+
|
|
96
|
+
// Render-group uniforms: shared between compute and fragment passes,
|
|
97
|
+
// updated manually each frame in updateBefore (compute lacks a camera context).
|
|
98
|
+
this._cameraNear = uniform( 0 ).setName( 'clusteredCameraNear' ).setGroup( renderGroup );
|
|
99
|
+
this._cameraFar = uniform( 0 ).setName( 'clusteredCameraFar' ).setGroup( renderGroup );
|
|
100
|
+
this._cameraViewMatrix = uniform( 'mat4' ).setName( 'clusteredCameraViewMatrix' ).setGroup( renderGroup );
|
|
101
|
+
this._cameraProjectionMatrix = uniform( 'mat4' ).setName( 'clusteredCameraProjectionMatrix' ).setGroup( renderGroup );
|
|
102
|
+
|
|
103
|
+
this._gridDimensions = uniform( new Vector2() );
|
|
104
|
+
|
|
105
|
+
this.updateBeforeType = NodeUpdateType.RENDER;
|
|
106
|
+
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Overwrites the default {@link LightsNode#customCacheKey} implementation by
|
|
111
|
+
* including the node identity and resource version into the cache key.
|
|
112
|
+
*
|
|
113
|
+
* @return {number} The custom cache key.
|
|
114
|
+
*/
|
|
115
|
+
customCacheKey() {
|
|
116
|
+
|
|
117
|
+
// First use allocates the grid after material cache keys have been computed.
|
|
118
|
+
// Keep that allocation stable, but never share bindings between lights nodes.
|
|
119
|
+
return NodeUtils.hash( this.id, this.version, super.customCacheKey() );
|
|
120
|
+
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Updates the light data and the light ranges of the depth slices.
|
|
125
|
+
*
|
|
126
|
+
* @private
|
|
127
|
+
* @param {Camera} camera - The camera.
|
|
128
|
+
*/
|
|
129
|
+
_updateLightsTexture( camera ) {
|
|
130
|
+
|
|
131
|
+
const { _lightsTexture: lightsTexture, clusteredLights } = this;
|
|
132
|
+
|
|
133
|
+
const data = lightsTexture.image.data;
|
|
134
|
+
const lineSize = lightsTexture.image.width * 4;
|
|
135
|
+
const count = Math.min( clusteredLights.length, this.maxLights );
|
|
136
|
+
|
|
137
|
+
this._lightsCount.value = count;
|
|
138
|
+
|
|
139
|
+
// Sort lights by the view-space depth of their bounding spheres for Z-culling
|
|
140
|
+
|
|
141
|
+
const viewZ = this._lightViewZ;
|
|
142
|
+
const order = this._lightSortOrder;
|
|
143
|
+
|
|
144
|
+
for ( let i = 0; i < count; i ++ ) {
|
|
145
|
+
|
|
146
|
+
this._getBoundingSphereCenter( clusteredLights[ i ], _vector3 );
|
|
147
|
+
_vector3.applyMatrix4( camera.matrixWorldInverse );
|
|
148
|
+
viewZ[ i ] = _vector3.z;
|
|
149
|
+
order[ i ] = i;
|
|
150
|
+
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
order.length = count;
|
|
154
|
+
order.sort( ( a, b ) => viewZ[ a ] - viewZ[ b ] );
|
|
155
|
+
|
|
156
|
+
// Write sorted lights to texture
|
|
157
|
+
|
|
158
|
+
for ( let i = 0; i < count; i ++ ) {
|
|
159
|
+
|
|
160
|
+
const light = clusteredLights[ order[ i ] ];
|
|
161
|
+
|
|
162
|
+
const offset = i * 4;
|
|
163
|
+
|
|
164
|
+
_vector3.setFromMatrixPosition( light.matrixWorld );
|
|
165
|
+
|
|
166
|
+
let rowOffset = lineSize * POSITION_ROW + offset;
|
|
167
|
+
|
|
168
|
+
data[ rowOffset + 0 ] = _vector3.x;
|
|
169
|
+
data[ rowOffset + 1 ] = _vector3.y;
|
|
170
|
+
data[ rowOffset + 2 ] = _vector3.z;
|
|
171
|
+
data[ rowOffset + 3 ] = light.distance;
|
|
172
|
+
|
|
173
|
+
rowOffset = lineSize * COLOR_ROW + offset;
|
|
174
|
+
|
|
175
|
+
data[ rowOffset + 0 ] = light.color.r * light.intensity;
|
|
176
|
+
data[ rowOffset + 1 ] = light.color.g * light.intensity;
|
|
177
|
+
data[ rowOffset + 2 ] = light.color.b * light.intensity;
|
|
178
|
+
data[ rowOffset + 3 ] = light.decay;
|
|
179
|
+
|
|
180
|
+
// The spot attenuation smoothstep( coneCos, penumbraCos, dot( L, direction ) ) is stored
|
|
181
|
+
// as smoothstep( 0, 1, dot( L, direction * scale ) - coneCos * scale ) with
|
|
182
|
+
// scale = 1 / ( penumbraCos - coneCos ). Point lights store a constant attenuation of 1.
|
|
183
|
+
|
|
184
|
+
rowOffset = lineSize * SPOT_ROW + offset;
|
|
185
|
+
|
|
186
|
+
if ( light.isSpotLight === true ) {
|
|
187
|
+
|
|
188
|
+
const coneCos = Math.cos( light.angle );
|
|
189
|
+
const penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
|
|
190
|
+
const scale = 1 / Math.max( penumbraCos - coneCos, 1e-4 );
|
|
191
|
+
|
|
192
|
+
this._getSpotDirection( light, _direction ).multiplyScalar( scale );
|
|
193
|
+
|
|
194
|
+
data[ rowOffset + 0 ] = _direction.x;
|
|
195
|
+
data[ rowOffset + 1 ] = _direction.y;
|
|
196
|
+
data[ rowOffset + 2 ] = _direction.z;
|
|
197
|
+
data[ rowOffset + 3 ] = coneCos * scale;
|
|
198
|
+
|
|
199
|
+
} else {
|
|
200
|
+
|
|
201
|
+
data[ rowOffset + 0 ] = 0;
|
|
202
|
+
data[ rowOffset + 1 ] = 0;
|
|
203
|
+
data[ rowOffset + 2 ] = 0;
|
|
204
|
+
data[ rowOffset + 3 ] = - 1;
|
|
205
|
+
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
this._getBoundingSphereCenter( light, _vector3 );
|
|
209
|
+
|
|
210
|
+
rowOffset = lineSize * BOUNDS_ROW + offset;
|
|
211
|
+
|
|
212
|
+
data[ rowOffset + 0 ] = _vector3.x;
|
|
213
|
+
data[ rowOffset + 1 ] = _vector3.y;
|
|
214
|
+
data[ rowOffset + 2 ] = _vector3.z;
|
|
215
|
+
data[ rowOffset + 3 ] = this._getBoundingSphereRadius( light );
|
|
216
|
+
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
lightsTexture.needsUpdate = true;
|
|
220
|
+
|
|
221
|
+
// Compute per Z-slice light ranges
|
|
222
|
+
|
|
223
|
+
const zRanges = this._zSliceRangesData;
|
|
224
|
+
|
|
225
|
+
const near = camera.near;
|
|
226
|
+
const far = camera.far;
|
|
227
|
+
const NZ = this.zSlices;
|
|
228
|
+
|
|
229
|
+
for ( let z = 0; z < NZ; z ++ ) {
|
|
230
|
+
|
|
231
|
+
// Exponential Z-slice bounds (view-space, negative values)
|
|
232
|
+
const sliceNear = - ( near * Math.pow( far / near, z / NZ ) );
|
|
233
|
+
const sliceFar = - ( near * Math.pow( far / near, ( z + 1 ) / NZ ) );
|
|
234
|
+
|
|
235
|
+
let rangeStart = count;
|
|
236
|
+
let rangeEnd = 0;
|
|
237
|
+
|
|
238
|
+
for ( let i = 0; i < count; i ++ ) {
|
|
239
|
+
|
|
240
|
+
const vz = viewZ[ order[ i ] ];
|
|
241
|
+
const r = data[ lineSize * BOUNDS_ROW + i * 4 + 3 ];
|
|
242
|
+
const radius = r >= 0 ? r : far;
|
|
243
|
+
|
|
244
|
+
// Bounding sphere Z: [vz - radius, vz + radius]
|
|
245
|
+
// Slice Z: [sliceFar, sliceNear] (both negative, sliceFar < sliceNear)
|
|
246
|
+
if ( vz + radius >= sliceFar && vz - radius <= sliceNear ) {
|
|
247
|
+
|
|
248
|
+
if ( i < rangeStart ) rangeStart = i;
|
|
249
|
+
if ( i + 1 > rangeEnd ) rangeEnd = i + 1;
|
|
250
|
+
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if ( rangeStart >= count ) {
|
|
256
|
+
|
|
257
|
+
rangeStart = 0;
|
|
258
|
+
rangeEnd = 0;
|
|
259
|
+
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
zRanges[ z * 4 ] = rangeStart;
|
|
263
|
+
zRanges[ z * 4 + 1 ] = rangeEnd;
|
|
264
|
+
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
this._zSliceRangesTexture.needsUpdate = true;
|
|
268
|
+
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Returns the normalized world-space direction pointing from the spot light's
|
|
273
|
+
* target to the spot light.
|
|
274
|
+
*
|
|
275
|
+
* @private
|
|
276
|
+
* @param {SpotLight} light - The spot light.
|
|
277
|
+
* @param {Vector3} target - The target vector.
|
|
278
|
+
* @return {Vector3} The direction.
|
|
279
|
+
*/
|
|
280
|
+
_getSpotDirection( light, target ) {
|
|
281
|
+
|
|
282
|
+
_targetPosition.setFromMatrixPosition( light.target.matrixWorld );
|
|
283
|
+
|
|
284
|
+
return target.setFromMatrixPosition( light.matrixWorld ).sub( _targetPosition ).normalize();
|
|
285
|
+
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Returns the world-space center of the light's bounding sphere. For spot lights,
|
|
290
|
+
* this is the center of the smallest sphere enclosing the cone.
|
|
291
|
+
*
|
|
292
|
+
* @private
|
|
293
|
+
* @param {PointLight|SpotLight} light - The light.
|
|
294
|
+
* @param {Vector3} target - The target vector.
|
|
295
|
+
* @return {Vector3} The bounding sphere center.
|
|
296
|
+
*/
|
|
297
|
+
_getBoundingSphereCenter( light, target ) {
|
|
298
|
+
|
|
299
|
+
target.setFromMatrixPosition( light.matrixWorld );
|
|
300
|
+
|
|
301
|
+
if ( light.isSpotLight === true && light.distance > 0 ) {
|
|
302
|
+
|
|
303
|
+
const angle = Math.min( light.angle, Math.PI / 2 );
|
|
304
|
+
const offset = angle > Math.PI / 4 ? light.distance * Math.cos( angle ) : light.distance / ( 2 * Math.cos( angle ) );
|
|
305
|
+
|
|
306
|
+
// _getSpotDirection() points away from the cone, so step backwards
|
|
307
|
+
|
|
308
|
+
target.addScaledVector( this._getSpotDirection( light, _direction ), - offset );
|
|
309
|
+
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return target;
|
|
313
|
+
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Returns the radius of the light's bounding sphere.
|
|
318
|
+
*
|
|
319
|
+
* @private
|
|
320
|
+
* @param {PointLight|SpotLight} light - The light.
|
|
321
|
+
* @return {number} The bounding sphere radius. `-1` if the light has no cutoff distance.
|
|
322
|
+
*/
|
|
323
|
+
_getBoundingSphereRadius( light ) {
|
|
324
|
+
|
|
325
|
+
if ( light.distance <= 0 ) return - 1;
|
|
326
|
+
|
|
327
|
+
if ( light.isSpotLight === true ) {
|
|
328
|
+
|
|
329
|
+
const angle = Math.min( light.angle, Math.PI / 2 );
|
|
330
|
+
|
|
331
|
+
return angle > Math.PI / 4 ? light.distance * Math.sin( angle ) : light.distance / ( 2 * Math.cos( angle ) );
|
|
332
|
+
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return light.distance;
|
|
336
|
+
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Updates the light data and assigns the lights to the clusters.
|
|
341
|
+
*
|
|
342
|
+
* @param {NodeFrame} frame - A reference to the current node frame.
|
|
343
|
+
*/
|
|
344
|
+
updateBefore( frame ) {
|
|
345
|
+
|
|
346
|
+
const { renderer, camera } = frame;
|
|
347
|
+
|
|
348
|
+
this._initGrid( renderer );
|
|
349
|
+
|
|
350
|
+
this._updateLightsTexture( camera );
|
|
351
|
+
|
|
352
|
+
this._cameraNear.value = camera.near;
|
|
353
|
+
this._cameraFar.value = camera.far;
|
|
354
|
+
this._cameraViewMatrix.value = camera.matrixWorldInverse;
|
|
355
|
+
this._cameraProjectionMatrix.value = camera.projectionMatrix;
|
|
356
|
+
|
|
357
|
+
renderer.compute( this._compute );
|
|
358
|
+
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Configures this node with an array of lights. Point and spot lights without
|
|
363
|
+
* shadows are clustered (except lights with a `colorNode`, spot lights with a
|
|
364
|
+
* projected `map` and light types with their own light node, like `IESSpotLight`
|
|
365
|
+
* or `ProjectorLight`), all other lights use the default lighting.
|
|
366
|
+
*
|
|
367
|
+
* @param {Array<Light>} lights - An array of lights.
|
|
368
|
+
* @return {ClusteredLightsNode} A reference to this node.
|
|
369
|
+
*/
|
|
370
|
+
setLights( lights ) {
|
|
371
|
+
|
|
372
|
+
const { clusteredLights, materialLights } = this;
|
|
373
|
+
|
|
374
|
+
let materialIndex = 0;
|
|
375
|
+
let clusteredIndex = 0;
|
|
376
|
+
|
|
377
|
+
for ( const light of lights ) {
|
|
378
|
+
|
|
379
|
+
if ( this._isClusteredLight( light ) ) {
|
|
380
|
+
|
|
381
|
+
clusteredLights[ clusteredIndex ++ ] = light;
|
|
382
|
+
|
|
383
|
+
} else {
|
|
384
|
+
|
|
385
|
+
materialLights[ materialIndex ++ ] = light;
|
|
386
|
+
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
materialLights.length = materialIndex;
|
|
392
|
+
clusteredLights.length = clusteredIndex;
|
|
393
|
+
|
|
394
|
+
return super.setLights( lights );
|
|
395
|
+
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Returns `true` if the given light can be clustered.
|
|
400
|
+
*
|
|
401
|
+
* @private
|
|
402
|
+
* @param {Light} light - The light.
|
|
403
|
+
* @return {boolean} Whether the light is clustered or not.
|
|
404
|
+
*/
|
|
405
|
+
_isClusteredLight( light ) {
|
|
406
|
+
|
|
407
|
+
// Shadows, color nodes (any light) and projected maps (spot lights) are not supported.
|
|
408
|
+
|
|
409
|
+
if ( light.castShadow === true || light.colorNode ) return false;
|
|
410
|
+
|
|
411
|
+
// Only lights shaded by the plain point and spot light nodes are clustered. Subclasses
|
|
412
|
+
// registered with their own light node (e.g. IESSpotLight, ProjectorLight) keep the
|
|
413
|
+
// default lighting, since clustering would shade them as plain spot lights.
|
|
414
|
+
|
|
415
|
+
if ( light._lightNode === PointLightNode ) return true;
|
|
416
|
+
|
|
417
|
+
return light._lightNode === SpotLightNode && ! light.map;
|
|
418
|
+
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Returns the lights that are not clustered.
|
|
423
|
+
*
|
|
424
|
+
* @return {Array<Light>} The lights using the default lighting.
|
|
425
|
+
*/
|
|
426
|
+
getBuiltinLights() {
|
|
427
|
+
|
|
428
|
+
return this.materialLights;
|
|
429
|
+
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Returns the light index stored at the given slot of the fragment's cluster.
|
|
434
|
+
*
|
|
435
|
+
* @private
|
|
436
|
+
* @param {number|Node<int>} element - The slot.
|
|
437
|
+
* @return {Node<int>} The 1-based light index. `0` marks the end of the list.
|
|
438
|
+
*/
|
|
439
|
+
_getTile( element ) {
|
|
440
|
+
|
|
441
|
+
element = int( element );
|
|
442
|
+
|
|
443
|
+
const stride = int( 4 );
|
|
444
|
+
const chunkOffset = element.div( stride );
|
|
445
|
+
const idx = this._screenClusterIndex.mul( int( this._chunksPerCluster ) ).add( chunkOffset );
|
|
446
|
+
|
|
447
|
+
return this._lightIndexes.element( idx ).element( element.mod( stride ) );
|
|
448
|
+
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Returns the number of lights in the fragment's cluster. Useful for debugging.
|
|
453
|
+
*
|
|
454
|
+
* @param {Node<int>} zSliceNode - The depth slice to inspect. A negative value selects the fragment's own cluster.
|
|
455
|
+
* @return {Node<int>} The light count.
|
|
456
|
+
*/
|
|
457
|
+
getClusterLightCount( zSliceNode ) {
|
|
458
|
+
|
|
459
|
+
const getCount = Fn( ( [ zSliceNode ] ) => {
|
|
460
|
+
|
|
461
|
+
const count = int( 0 ).toVar();
|
|
462
|
+
|
|
463
|
+
const debugClusterIndex = this._screenClusterIndex.toVar();
|
|
464
|
+
|
|
465
|
+
If( zSliceNode.greaterThanEqual( int( 0 ) ), () => {
|
|
466
|
+
|
|
467
|
+
const tileSize = int( this.tileSize );
|
|
468
|
+
const screenTile = screenCoordinate.div( tileSize ).floor();
|
|
469
|
+
const NX = int( this._gridDimensions.x );
|
|
470
|
+
const NY = int( this._gridDimensions.y );
|
|
471
|
+
|
|
472
|
+
debugClusterIndex.assign(
|
|
473
|
+
int( screenTile.x )
|
|
474
|
+
.add( int( screenTile.y ).mul( NX ) )
|
|
475
|
+
.add( zSliceNode.mul( NX.mul( NY ) ) )
|
|
476
|
+
);
|
|
477
|
+
|
|
478
|
+
} );
|
|
479
|
+
|
|
480
|
+
Loop( this.maxLightsPerCluster, ( { i } ) => {
|
|
481
|
+
|
|
482
|
+
const element = int( i );
|
|
483
|
+
const stride = int( 4 );
|
|
484
|
+
const chunkOffset = element.div( stride );
|
|
485
|
+
const idx = debugClusterIndex.mul( int( this._chunksPerCluster ) ).add( chunkOffset );
|
|
486
|
+
const lightIndex = this._lightIndexes.element( idx ).element( element.mod( stride ) );
|
|
487
|
+
|
|
488
|
+
If( lightIndex.equal( int( 0 ) ), () => {
|
|
489
|
+
|
|
490
|
+
Break();
|
|
491
|
+
|
|
492
|
+
} );
|
|
493
|
+
|
|
494
|
+
count.addAssign( int( 1 ) );
|
|
495
|
+
|
|
496
|
+
} );
|
|
497
|
+
|
|
498
|
+
return count;
|
|
499
|
+
|
|
500
|
+
} );
|
|
501
|
+
|
|
502
|
+
return getCount( zSliceNode );
|
|
503
|
+
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Returns the shading data of the light at the given index.
|
|
508
|
+
*
|
|
509
|
+
* @private
|
|
510
|
+
* @param {number|Node<int>} index - The light index.
|
|
511
|
+
* @return {Object} The light's view position, distance, color, decay, view-space spot direction and spot offset.
|
|
512
|
+
*/
|
|
513
|
+
_getLightData( index ) {
|
|
514
|
+
|
|
515
|
+
index = int( index );
|
|
516
|
+
|
|
517
|
+
const dataA = textureLoad( this._lightsTexture, ivec2( index, POSITION_ROW ) );
|
|
518
|
+
const dataB = textureLoad( this._lightsTexture, ivec2( index, COLOR_ROW ) );
|
|
519
|
+
const dataC = textureLoad( this._lightsTexture, ivec2( index, SPOT_ROW ) );
|
|
520
|
+
|
|
521
|
+
const viewPosition = this._cameraViewMatrix.mul( vec4( dataA.xyz, 1.0 ) ).xyz;
|
|
522
|
+
const distance = dataA.w;
|
|
523
|
+
const color = dataB.rgb;
|
|
524
|
+
const decay = dataB.w;
|
|
525
|
+
const spotDirection = this._cameraViewMatrix.mul( vec4( dataC.xyz, 0.0 ) ).xyz;
|
|
526
|
+
const spotOffset = dataC.w;
|
|
527
|
+
|
|
528
|
+
return {
|
|
529
|
+
viewPosition,
|
|
530
|
+
distance,
|
|
531
|
+
color,
|
|
532
|
+
decay,
|
|
533
|
+
spotDirection,
|
|
534
|
+
spotOffset
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Returns the culling data of the light at the given index.
|
|
541
|
+
*
|
|
542
|
+
* @private
|
|
543
|
+
* @param {number|Node<int>} index - The light index.
|
|
544
|
+
* @return {Object} The view-space center and the radius of the light's bounding sphere. A negative radius marks an unbounded light.
|
|
545
|
+
*/
|
|
546
|
+
_getLightBounds( index ) {
|
|
547
|
+
|
|
548
|
+
const data = textureLoad( this._lightsTexture, ivec2( int( index ), BOUNDS_ROW ) );
|
|
549
|
+
|
|
550
|
+
const center = this._cameraViewMatrix.mul( vec4( data.xyz, 1.0 ) ).xyz;
|
|
551
|
+
const radius = data.w;
|
|
552
|
+
|
|
553
|
+
return { center, radius };
|
|
554
|
+
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Sets up the default lights and the clustered point and spot lights.
|
|
559
|
+
*
|
|
560
|
+
* @param {NodeBuilder} builder - A reference to the current node builder.
|
|
561
|
+
* @param {Array<LightingNode>} lightNodes - An array of lighting nodes.
|
|
562
|
+
*/
|
|
563
|
+
setupLights( builder, lightNodes ) {
|
|
564
|
+
|
|
565
|
+
this._initGrid( builder.renderer );
|
|
566
|
+
|
|
567
|
+
//
|
|
568
|
+
|
|
569
|
+
const lightingModel = builder.context.reflectedLight;
|
|
570
|
+
|
|
571
|
+
lightingModel.directDiffuse.toStack();
|
|
572
|
+
lightingModel.directSpecular.toStack();
|
|
573
|
+
|
|
574
|
+
super.setupLights( builder, lightNodes );
|
|
575
|
+
|
|
576
|
+
Fn( () => {
|
|
577
|
+
|
|
578
|
+
Loop( this.maxLightsPerCluster, ( { i } ) => {
|
|
579
|
+
|
|
580
|
+
const lightIndex = this._getTile( i );
|
|
581
|
+
|
|
582
|
+
If( lightIndex.equal( int( 0 ) ), () => {
|
|
583
|
+
|
|
584
|
+
Break();
|
|
585
|
+
|
|
586
|
+
} );
|
|
587
|
+
|
|
588
|
+
const { color, decay, viewPosition, distance, spotDirection, spotOffset } = this._getLightData( lightIndex.sub( 1 ) );
|
|
589
|
+
|
|
590
|
+
const lightVector = viewPosition.sub( positionView );
|
|
591
|
+
|
|
592
|
+
// spot cone attenuation, always 1 for point lights
|
|
593
|
+
const spotAttenuation = smoothstep( 0, 1, dot( lightVector.normalize(), spotDirection ).sub( spotOffset ) ).toVar();
|
|
594
|
+
|
|
595
|
+
// Early-out: skip full BRDF if fragment is beyond the light's cutoff or outside the spot cone
|
|
596
|
+
const inRange = distance.equal( 0 ).or( dot( lightVector, lightVector ).lessThanEqual( distance.mul( distance ) ) );
|
|
597
|
+
|
|
598
|
+
If( inRange.and( spotAttenuation.greaterThan( 0 ) ), () => {
|
|
599
|
+
|
|
600
|
+
builder.lightsNode.setupDirectLight( builder, this, directPointLight( {
|
|
601
|
+
color: color.mul( spotAttenuation ),
|
|
602
|
+
lightVector,
|
|
603
|
+
cutoffDistance: distance,
|
|
604
|
+
decayExponent: decay
|
|
605
|
+
} ) );
|
|
606
|
+
|
|
607
|
+
} );
|
|
608
|
+
|
|
609
|
+
} );
|
|
610
|
+
|
|
611
|
+
}, 'void' )();
|
|
612
|
+
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Rounds the given size up to a multiple of the tile size.
|
|
617
|
+
*
|
|
618
|
+
* @private
|
|
619
|
+
* @param {number} value - The size.
|
|
620
|
+
* @return {number} The fitted size.
|
|
621
|
+
*/
|
|
622
|
+
_getBufferFitSize( value ) {
|
|
623
|
+
|
|
624
|
+
const multiple = this.tileSize;
|
|
625
|
+
|
|
626
|
+
return Math.ceil( value / multiple ) * multiple;
|
|
627
|
+
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* Sets the size of the cluster grid. Must be called outside of rendering. Not required
|
|
632
|
+
* with {@link ClusteredLighting}, which fits the grid at the beginning of each render.
|
|
633
|
+
*
|
|
634
|
+
* @param {number} width - The drawing buffer width.
|
|
635
|
+
* @param {number} height - The drawing buffer height.
|
|
636
|
+
* @return {ClusteredLightsNode} A reference to this node.
|
|
637
|
+
*/
|
|
638
|
+
setSize( width, height ) {
|
|
639
|
+
|
|
640
|
+
this._resize( this._getBufferFitSize( width ), this._getBufferFitSize( height ) );
|
|
641
|
+
|
|
642
|
+
return this;
|
|
643
|
+
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* Fits the cluster grid to the framebuffer of the render that is about to start. Called by
|
|
648
|
+
* {@link ClusteredLighting} before the render objects of the render are prepared. Since each
|
|
649
|
+
* render depth has its own node, no pending command buffer uses the resources of this node at
|
|
650
|
+
* this point, so a rebuild can free the replaced resources immediately.
|
|
651
|
+
*/
|
|
652
|
+
updateSize() {
|
|
653
|
+
|
|
654
|
+
if ( this._renderer !== null ) this._fitToRenderer( this._renderer );
|
|
655
|
+
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* Creates the cluster grid on first use. While rendering, the grid is never rebuilt: the
|
|
660
|
+
* replaced resources could still be used by a command buffer that was not submitted yet.
|
|
661
|
+
*
|
|
662
|
+
* @private
|
|
663
|
+
* @param {Renderer} renderer - The renderer.
|
|
664
|
+
*/
|
|
665
|
+
_initGrid( renderer ) {
|
|
666
|
+
|
|
667
|
+
this._renderer = renderer;
|
|
668
|
+
|
|
669
|
+
if ( this._compute === null ) this._fitToRenderer( renderer );
|
|
670
|
+
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Fits the cluster grid to the framebuffer the renderer is rendering to.
|
|
675
|
+
*
|
|
676
|
+
* @private
|
|
677
|
+
* @param {Renderer} renderer - The renderer.
|
|
678
|
+
*/
|
|
679
|
+
_fitToRenderer( renderer ) {
|
|
680
|
+
|
|
681
|
+
// the grid must match the framebuffer being rendered: a render target (e.g. a reflector
|
|
682
|
+
// with a resolution scale) can differ from the drawing buffer
|
|
683
|
+
|
|
684
|
+
const renderTarget = renderer.getRenderTarget();
|
|
685
|
+
|
|
686
|
+
if ( renderTarget !== null ) {
|
|
687
|
+
|
|
688
|
+
_size.set( renderTarget.width, renderTarget.height );
|
|
689
|
+
|
|
690
|
+
} else {
|
|
691
|
+
|
|
692
|
+
renderer.getDrawingBufferSize( _size );
|
|
693
|
+
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// the compute differs per backend, so a backend change requires a rebuild
|
|
697
|
+
|
|
698
|
+
const isWebGLBackend = renderer.backend.isWebGLBackend === true;
|
|
699
|
+
|
|
700
|
+
if ( this._compute !== null && this._isWebGLBackend !== isWebGLBackend ) this._needsRebuild = true;
|
|
701
|
+
|
|
702
|
+
this._isWebGLBackend = isWebGLBackend;
|
|
703
|
+
|
|
704
|
+
this._resize( this._getBufferFitSize( _size.width ), this._getBufferFitSize( _size.height ) );
|
|
705
|
+
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* Resizes the cluster grid. The grid dimensions are uniforms, so resizing only updates
|
|
710
|
+
* them and the compute count; the compute and the storage are rebuilt only when the
|
|
711
|
+
* storage has to grow (or the backend changed).
|
|
712
|
+
*
|
|
713
|
+
* @private
|
|
714
|
+
* @param {number} width - The fitted width.
|
|
715
|
+
* @param {number} height - The fitted height.
|
|
716
|
+
*/
|
|
717
|
+
_resize( width, height ) {
|
|
718
|
+
|
|
719
|
+
if ( this._needsRebuild === false && this._bufferSize !== null && this._bufferSize.width === width && this._bufferSize.height === height ) return;
|
|
720
|
+
|
|
721
|
+
const NX = Math.floor( width / this.tileSize );
|
|
722
|
+
const NY = Math.floor( height / this.tileSize );
|
|
723
|
+
const clusterCount = NX * NY * this.zSlices;
|
|
724
|
+
|
|
725
|
+
const requiredElements = clusterCount * this._chunksPerCluster;
|
|
726
|
+
|
|
727
|
+
if ( this._needsRebuild === true || this._compute === null || this._lightIndexes.value.array.length / 4 < requiredElements ) {
|
|
728
|
+
|
|
729
|
+
this._create( clusterCount );
|
|
730
|
+
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
this._gridDimensions.value.set( NX, NY );
|
|
734
|
+
this._compute.count = clusterCount * this._invocationsPerCluster;
|
|
735
|
+
|
|
736
|
+
if ( this._bufferSize === null ) this._bufferSize = new Vector2();
|
|
737
|
+
|
|
738
|
+
this._bufferSize.set( width, height );
|
|
739
|
+
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* Creates the light index storage, the compute node and the fragment cluster lookup.
|
|
744
|
+
* The storage is allocated with headroom so that most resizes do not need a rebuild.
|
|
745
|
+
*
|
|
746
|
+
* @private
|
|
747
|
+
* @param {number} clusterCount - The number of clusters of the current grid.
|
|
748
|
+
*/
|
|
749
|
+
_create( clusterCount ) {
|
|
750
|
+
|
|
751
|
+
const { tileSize, zSlices, _chunksPerCluster: chunksPerCluster } = this;
|
|
752
|
+
|
|
753
|
+
const NZ = zSlices;
|
|
754
|
+
|
|
755
|
+
// grid dimensions as uniforms: shaders do not depend on the drawing buffer size
|
|
756
|
+
|
|
757
|
+
const grid = this._gridDimensions;
|
|
758
|
+
const NX = int( grid.x );
|
|
759
|
+
const NY = int( grid.y );
|
|
760
|
+
|
|
761
|
+
// Per-cluster light-index storage (ivec4 chunks), grown geometrically.
|
|
762
|
+
|
|
763
|
+
const requiredElements = clusterCount * chunksPerCluster;
|
|
764
|
+
const previousElements = this._lightIndexes !== null ? this._lightIndexes.value.array.length / 4 : 0;
|
|
765
|
+
const elements = previousElements === 0 ? Math.ceil( requiredElements * 1.5 ) : Math.max( requiredElements, previousElements * 2 );
|
|
766
|
+
|
|
767
|
+
// rebuilds only happen outside of rendering (see _initGrid()), so the replaced resources can be freed
|
|
768
|
+
|
|
769
|
+
if ( this._compute !== null ) {
|
|
770
|
+
|
|
771
|
+
// Replacing storage requires new material bindings. The initial allocation does not.
|
|
772
|
+
this.needsUpdate = true;
|
|
773
|
+
|
|
774
|
+
this._compute.dispose();
|
|
775
|
+
this._lightIndexes.value.dispose();
|
|
776
|
+
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// instanced storage: WebGL computes use gl_InstanceID as instanceIndex; PBO: random access in the fragment stage
|
|
780
|
+
const lightIndexes = instancedArray( new Int32Array( elements * 4 ), 'ivec4' ).setPBO( true ).setName( 'lightIndexes' );
|
|
781
|
+
|
|
782
|
+
// view-space AABB of the given cluster
|
|
783
|
+
|
|
784
|
+
const getClusterBounds = ( clusterIndex ) => {
|
|
785
|
+
|
|
786
|
+
// view-space scale factors derived from the projection matrix:
|
|
787
|
+
// view_x = ndc_x * (-view_z) / focal_x = ndc_x * (-view_z) * invFocalX
|
|
788
|
+
// view_y = ndc_y * (-view_z) / focal_y = ndc_y * (-view_z) * invFocalY
|
|
789
|
+
// where focal_x = projMatrix[0][0] and focal_y = projMatrix[1][1].
|
|
790
|
+
const invFocalX = float( 1 ).div( this._cameraProjectionMatrix.element( 0 ).element( 0 ) );
|
|
791
|
+
const invFocalY = float( 1 ).div( this._cameraProjectionMatrix.element( 1 ).element( 1 ) );
|
|
792
|
+
|
|
793
|
+
// 3D cluster coordinates
|
|
794
|
+
const cx = clusterIndex.mod( NX );
|
|
795
|
+
const cy = clusterIndex.div( NX ).mod( NY );
|
|
796
|
+
const cz = clusterIndex.div( NX.mul( NY ) );
|
|
797
|
+
|
|
798
|
+
// NDC X/Y bounds of the cluster.
|
|
799
|
+
// Y is flipped: cy=0 is the top screen row (fragment y=0), which is NDC y=+1.
|
|
800
|
+
const ndcXmin = float( cx ).mul( 2.0 ).div( grid.x ).sub( 1.0 );
|
|
801
|
+
const ndcXmax = float( cx.add( int( 1 ) ) ).mul( 2.0 ).div( grid.x ).sub( 1.0 );
|
|
802
|
+
const ndcYmax = float( 1 ).sub( float( cy ).mul( 2.0 ).div( grid.y ) );
|
|
803
|
+
const ndcYmin = float( 1 ).sub( float( cy.add( int( 1 ) ) ).mul( 2.0 ).div( grid.y ) );
|
|
804
|
+
|
|
805
|
+
// View-space Z bounds (negative, exponential slicing)
|
|
806
|
+
const farOverNear = this._cameraFar.div( this._cameraNear );
|
|
807
|
+
const zNearCluster = this._cameraNear.mul( pow( farOverNear, float( cz ).mul( 1.0 / NZ ) ) ).negate();
|
|
808
|
+
const zFarCluster = this._cameraNear.mul( pow( farOverNear, float( cz.add( int( 1 ) ) ).mul( 1.0 / NZ ) ) ).negate();
|
|
809
|
+
|
|
810
|
+
const scaleNearX = zNearCluster.negate().mul( invFocalX );
|
|
811
|
+
const scaleFarX = zFarCluster.negate().mul( invFocalX );
|
|
812
|
+
const scaleNearY = zNearCluster.negate().mul( invFocalY );
|
|
813
|
+
const scaleFarY = zFarCluster.negate().mul( invFocalY );
|
|
814
|
+
|
|
815
|
+
const xMinNear = ndcXmin.mul( scaleNearX );
|
|
816
|
+
const xMaxNear = ndcXmax.mul( scaleNearX );
|
|
817
|
+
const xMinFar = ndcXmin.mul( scaleFarX );
|
|
818
|
+
const xMaxFar = ndcXmax.mul( scaleFarX );
|
|
819
|
+
|
|
820
|
+
const yMinNear = ndcYmin.mul( scaleNearY );
|
|
821
|
+
const yMaxNear = ndcYmax.mul( scaleNearY );
|
|
822
|
+
const yMinFar = ndcYmin.mul( scaleFarY );
|
|
823
|
+
const yMaxFar = ndcYmax.mul( scaleFarY );
|
|
824
|
+
|
|
825
|
+
// AABB of the 8 view-space corners (tile boundaries can straddle the view axis)
|
|
826
|
+
const aabbMinX = min( xMinNear, xMinFar );
|
|
827
|
+
const aabbMaxX = max( xMaxNear, xMaxFar );
|
|
828
|
+
const aabbMinY = min( yMinNear, yMinFar );
|
|
829
|
+
const aabbMaxY = max( yMaxNear, yMaxFar );
|
|
830
|
+
|
|
831
|
+
const aabbMin = vec3( aabbMinX, aabbMinY, zFarCluster );
|
|
832
|
+
const aabbMax = vec3( aabbMaxX, aabbMaxY, zNearCluster );
|
|
833
|
+
|
|
834
|
+
return { cz, aabbMin, aabbMax };
|
|
835
|
+
|
|
836
|
+
};
|
|
837
|
+
|
|
838
|
+
// sphere-AABB intersection in view space
|
|
839
|
+
|
|
840
|
+
const intersectsCluster = ( lightIdx, aabbMin, aabbMax ) => {
|
|
841
|
+
|
|
842
|
+
const { center, radius } = this._getLightBounds( lightIdx );
|
|
843
|
+
|
|
844
|
+
const closest = max( aabbMin, min( center, aabbMax ) );
|
|
845
|
+
const diff = center.sub( closest );
|
|
846
|
+
const distSq = dot( diff, diff );
|
|
847
|
+
|
|
848
|
+
return radius.lessThan( 0 ).or( distSq.lessThanEqual( radius.mul( radius ) ) );
|
|
849
|
+
|
|
850
|
+
};
|
|
851
|
+
|
|
852
|
+
// Each invocation fills `chunksPerInvocation` ivec4 chunks of one cluster. WebGL computes
|
|
853
|
+
// run via transform feedback and can only write their own element, so there each
|
|
854
|
+
// invocation fills a single chunk; WebGPU uses one invocation per cluster.
|
|
855
|
+
|
|
856
|
+
const chunksPerInvocation = this._isWebGLBackend ? 1 : chunksPerCluster;
|
|
857
|
+
const invocationsPerCluster = chunksPerCluster / chunksPerInvocation;
|
|
858
|
+
|
|
859
|
+
this._invocationsPerCluster = invocationsPerCluster;
|
|
860
|
+
|
|
861
|
+
const compute = Fn( () => {
|
|
862
|
+
|
|
863
|
+
const clusterIndex = int( instanceIndex.div( invocationsPerCluster ) );
|
|
864
|
+
const firstChunk = int( instanceIndex.mod( invocationsPerCluster ) ).mul( chunksPerInvocation );
|
|
865
|
+
const firstSlot = firstChunk.mul( 4 );
|
|
866
|
+
const lastSlot = firstSlot.add( chunksPerInvocation * 4 );
|
|
867
|
+
|
|
868
|
+
const { cz, aabbMin, aabbMax } = getClusterBounds( clusterIndex );
|
|
869
|
+
|
|
870
|
+
const chunks = ivec4( 0 ).toArray( chunksPerInvocation ).toVar();
|
|
871
|
+
const index = int( 0 ).toVar();
|
|
872
|
+
|
|
873
|
+
// Z-culling: only test lights that can reach this cluster's Z-slice
|
|
874
|
+
const zRange = textureLoad( this._zSliceRangesTexture, ivec2( cz, 0 ) );
|
|
875
|
+
const rangeStart = int( zRange.x );
|
|
876
|
+
const rangeEnd = int( zRange.y );
|
|
877
|
+
|
|
878
|
+
Loop( this.maxLights, ( { i } ) => {
|
|
879
|
+
|
|
880
|
+
const lightIdx = rangeStart.add( i );
|
|
881
|
+
|
|
882
|
+
If( index.greaterThanEqual( lastSlot ).or( lightIdx.greaterThanEqual( rangeEnd ) ), () => {
|
|
883
|
+
|
|
884
|
+
Break();
|
|
885
|
+
|
|
886
|
+
} );
|
|
887
|
+
|
|
888
|
+
If( intersectsCluster( lightIdx, aabbMin, aabbMax ), () => {
|
|
889
|
+
|
|
890
|
+
// slots before firstSlot belong to other invocations of this cluster
|
|
891
|
+
If( index.greaterThanEqual( firstSlot ), () => {
|
|
892
|
+
|
|
893
|
+
const slot = index.sub( firstSlot );
|
|
894
|
+
|
|
895
|
+
chunks.element( slot.div( 4 ) ).element( slot.mod( 4 ) ).assign( lightIdx.add( int( 1 ) ) );
|
|
896
|
+
|
|
897
|
+
} );
|
|
898
|
+
|
|
899
|
+
index.addAssign( int( 1 ) );
|
|
900
|
+
|
|
901
|
+
} );
|
|
902
|
+
|
|
903
|
+
} );
|
|
904
|
+
|
|
905
|
+
const firstElement = clusterIndex.mul( chunksPerCluster ).add( firstChunk );
|
|
906
|
+
|
|
907
|
+
const writeChunks = () => {
|
|
908
|
+
|
|
909
|
+
Loop( chunksPerInvocation, ( { i } ) => {
|
|
910
|
+
|
|
911
|
+
lightIndexes.element( firstElement.add( i ) ).assign( chunks.element( i ) );
|
|
912
|
+
|
|
913
|
+
} );
|
|
914
|
+
|
|
915
|
+
};
|
|
916
|
+
|
|
917
|
+
if ( this._isWebGLBackend === true ) {
|
|
918
|
+
|
|
919
|
+
// WebGL binds the transform feedback buffers per compute program, and programs are shared by
|
|
920
|
+
// identical code. The (always true) capacity and node id constants give each node and storage
|
|
921
|
+
// allocation its own program, so a compute never writes to the storage of another one.
|
|
922
|
+
|
|
923
|
+
If( firstElement.lessThan( int( elements ) ).and( int( this.id ).notEqual( int( - 1 ) ) ), writeChunks );
|
|
924
|
+
|
|
925
|
+
} else {
|
|
926
|
+
|
|
927
|
+
writeChunks();
|
|
928
|
+
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
} )().compute( clusterCount * invocationsPerCluster ).setName( 'Update Clustered Lights' );
|
|
932
|
+
|
|
933
|
+
// shading-side: fragment → cluster index
|
|
934
|
+
|
|
935
|
+
const getScreenClusterIndex = Fn( () => {
|
|
936
|
+
|
|
937
|
+
const screenTile = screenCoordinate.div( tileSize ).floor();
|
|
938
|
+
|
|
939
|
+
// view-space depth from positionView (negative in front); take magnitude
|
|
940
|
+
const viewDepth = positionView.z.negate();
|
|
941
|
+
|
|
942
|
+
// exponential Z slice: tz = floor( log(depth/near) / log(far/near) * NZ )
|
|
943
|
+
const invLogFarOverNear = float( 1 ).div( log( this._cameraFar.div( this._cameraNear ) ) );
|
|
944
|
+
const sliceFloat = log( viewDepth.div( this._cameraNear ) ).mul( invLogFarOverNear ).mul( float( NZ ) );
|
|
945
|
+
const zSlice = clamp( sliceFloat.floor(), float( 0 ), float( NZ - 1 ) );
|
|
946
|
+
|
|
947
|
+
return int( screenTile.x )
|
|
948
|
+
.add( int( screenTile.y ).mul( NX ) )
|
|
949
|
+
.add( int( zSlice ).mul( NX.mul( NY ) ) );
|
|
950
|
+
|
|
951
|
+
} );
|
|
952
|
+
|
|
953
|
+
const screenClusterIndex = getScreenClusterIndex().toVar();
|
|
954
|
+
|
|
955
|
+
// assigns
|
|
956
|
+
|
|
957
|
+
this._lightIndexes = lightIndexes;
|
|
958
|
+
this._screenClusterIndex = screenClusterIndex;
|
|
959
|
+
this._compute = compute;
|
|
960
|
+
this._needsRebuild = false;
|
|
961
|
+
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
/**
|
|
965
|
+
* Frees the GPU resources allocated by this node.
|
|
966
|
+
*/
|
|
967
|
+
dispose() {
|
|
968
|
+
|
|
969
|
+
if ( this._compute !== null ) this._compute.dispose();
|
|
970
|
+
if ( this._lightIndexes !== null ) this._lightIndexes.value.dispose();
|
|
971
|
+
|
|
972
|
+
this._lightsTexture.dispose();
|
|
973
|
+
this._zSliceRangesTexture.dispose();
|
|
974
|
+
|
|
975
|
+
super.dispose();
|
|
976
|
+
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
export default ClusteredLightsNode;
|
|
982
|
+
|
|
983
|
+
/**
|
|
984
|
+
* TSL function that creates a clustered lights node.
|
|
985
|
+
*
|
|
986
|
+
* @tsl
|
|
987
|
+
* @function
|
|
988
|
+
* @param {number} [maxLights=1024] - Maximum number of point and spot lights.
|
|
989
|
+
* @param {number} [tileSize=32] - Screen tile size in pixels.
|
|
990
|
+
* @param {number} [zSlices=24] - Depth slice count.
|
|
991
|
+
* @param {number} [maxLightsPerCluster=64] - Per-cluster light-list capacity.
|
|
992
|
+
* @return {ClusteredLightsNode} The clustered lights node.
|
|
993
|
+
*/
|
|
994
|
+
export const clusteredLights = /*@__PURE__*/ nodeProxy( ClusteredLightsNode );
|