@lampdotdev/lamp 0.0.0-stage → 0.36.2-nightly.16
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 +397 -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 +1813 -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/page/lamp-live.js +672 -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 +3042 -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/share-rules.json +64 -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 +416 -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 +62 -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 +170 -0
- package/Resources/skills/web-game/SKILL.md +95 -0
- package/Resources/skills/web-or-native/SKILL.md +108 -0
- package/Resources/skills/wish-links/SKILL.md +156 -0
- package/THIRD_PARTY_NOTICES.md +170 -0
- package/cli/ai.mjs +237 -0
- package/cli/android.mjs +941 -0
- package/cli/app-ai.mjs +473 -0
- package/cli/browser.mjs +284 -0
- package/cli/calls.mjs +594 -0
- package/cli/dev.mjs +820 -0
- package/cli/devices.mjs +984 -0
- package/cli/lamp.mjs +1326 -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 +6922 -0
- package/cli/lamps/lamp.js +7082 -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 +18215 -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 +7082 -0
- package/cli/lamps/web-starter/style.css +25 -0
- package/cli/link.mjs +202 -0
- package/cli/local-ai.mjs +193 -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/openrouter.mjs +133 -0
- package/cli/outside.mjs +203 -0
- package/cli/page.js +317 -0
- package/cli/place.mjs +298 -0
- package/cli/png.mjs +184 -0
- package/cli/share.mjs +270 -0
- package/cli/skill/SKILL.md +280 -0
- package/cli/skills.mjs +71 -0
- package/cli/state.mjs +176 -0
- package/cli/update.mjs +162 -0
- package/package.json +20 -4
- package/site/lib/quota.js +59 -0
- package/site/lib/shared-wishes.js +1727 -0
|
@@ -0,0 +1,1430 @@
|
|
|
1
|
+
import { Break, Continue, Fn, If, Loop, abs, bool, cross, distance, div, dot, float, getScreenPosition, getViewPosition, int, luminance, max, min, mix, mul, nodeObject, normalize, orthographicDepthToViewZ, passTexture, perspectiveDepthToViewZ, reference, reflect, sub, texture, textureSize, trunc, uniform, uv, vec2, vec3, vec4, context, isBackgroundDepth, projectionDepth } from 'three/tsl';
|
|
2
|
+
import { HalfFloatType, LinearFilter, LinearMipmapLinearFilter, Matrix4, NodeMaterial, NodeUpdateType, QuadMesh, RenderTarget, RendererUtils, Node, Vector2, Vector3 } from 'three/webgpu';
|
|
3
|
+
import { bindAnalyticNoise } from '../utils/RNoise.js';
|
|
4
|
+
import { ENV_RAY_LENGTH, getSpecularDominantFactor, ggxReflectionSample } from '../utils/SpecularHelpers.js';
|
|
5
|
+
import { boxBlur } from './boxBlur.js';
|
|
6
|
+
import ImportanceSampledEnvironment from './ImportanceSampledEnvironment.js';
|
|
7
|
+
|
|
8
|
+
const _quadMesh = /*@__PURE__*/ new QuadMesh();
|
|
9
|
+
const _size = /*@__PURE__*/ new Vector2();
|
|
10
|
+
let _rendererState;
|
|
11
|
+
|
|
12
|
+
// Maximum ray-march step count; `quality` (0..1) scales it to a fixed per-ray count.
|
|
13
|
+
const MAX_STEPS = 64;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {Object} SSRNodeOptions
|
|
17
|
+
* @property {boolean} [stochastic=false] - When `false`, traces a single mirror reflection and softens roughness with a blur pass (first-generation SSR). When `true`, varies the reflection direction per pixel with stochastic GGX rays (second-generation SSR); higher quality on rough/glossy surfaces but noisier, so it expects a temporal/spatial denoiser downstream.
|
|
18
|
+
* @property {Node<float>} [metalnessNode=null] - Per-pixel metalness. Drives GGX reflection sampling and, with `reflectNonMetals=false`, the non-metal early-out.
|
|
19
|
+
* @property {Node<vec3>} [specularNode=null] - Stochastic mode only: material normal-incidence reflectance (F0), typically an MRT `specularColorBlended` attachment (it already includes IOR, specular intensity and metalness; raw `material.specularColor` reflects too brightly). Defaults to the metalness/base-color approximation.
|
|
20
|
+
* @property {Node<float>} [specularF90Node=null] - Stochastic mode only: material grazing reflectance, typically an MRT `specularF90` attachment. Defaults to one.
|
|
21
|
+
* @property {Node<float>} [roughnessNode=null] - Per-pixel roughness. Drives GGX sampling and the blur mip selection.
|
|
22
|
+
* @property {boolean} [reflectNonMetals=false] - Only used when `stochastic=false`. When `false`, non-metallic surfaces are discarded for a noticeable performance gain; set `true` to also reflect dielectrics (e.g. marble, polished wood, plastic).
|
|
23
|
+
* @property {Texture} [environmentNode=null] - Equirectangular HDR environment map with CPU-side `image.data` (e.g. from RGBELoader). Not compatible with PMREM / `scene.environment` cubemaps.
|
|
24
|
+
* @property {boolean} [envImportanceSampling=false] - When `true`, precomputes env-luminance CDF tables and uses MIS for environment misses. Build-time only.
|
|
25
|
+
* @property {Node} [diffuseNode=null] - Scene diffuse / base color. Defaults to `vec3(1)` in the shader when omitted.
|
|
26
|
+
* @property {boolean} [binaryRefine=false] - Sub-step binary-search refinement of detected hits. Compile-time constant (baked into the shader at construction).
|
|
27
|
+
* @property {Camera} [camera=null] - Camera the scene is rendered with. Inferred from the color pass when omitted.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Post processing node for computing screen space reflections (SSR).
|
|
32
|
+
*
|
|
33
|
+
* Reference: {@link https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-reflection.html}
|
|
34
|
+
*
|
|
35
|
+
* @augments Node
|
|
36
|
+
* @three_import import { ssr } from 'three/addons/tsl/display/SSRNode.js';
|
|
37
|
+
*/
|
|
38
|
+
class SSRNode extends Node {
|
|
39
|
+
|
|
40
|
+
static get type() {
|
|
41
|
+
|
|
42
|
+
return 'SSRNode';
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Constructs a new SSR node.
|
|
48
|
+
*
|
|
49
|
+
* @param {Node<vec4>} colorNode - The node that represents the beauty pass.
|
|
50
|
+
* @param {Node<float>} depthNode - A node that represents the beauty pass's depth.
|
|
51
|
+
* @param {Node<vec3>} normalNode - A node that represents the beauty pass's normals.
|
|
52
|
+
* @param {SSRNodeOptions} [options] - Optional inputs for material and environment data.
|
|
53
|
+
*/
|
|
54
|
+
constructor( colorNode, depthNode, normalNode, options = {} ) {
|
|
55
|
+
|
|
56
|
+
super( 'vec4' );
|
|
57
|
+
|
|
58
|
+
const {
|
|
59
|
+
stochastic = false,
|
|
60
|
+
metalnessNode = null,
|
|
61
|
+
specularNode = null,
|
|
62
|
+
specularF90Node = null,
|
|
63
|
+
roughnessNode = null,
|
|
64
|
+
reflectNonMetals = false,
|
|
65
|
+
environmentNode = null,
|
|
66
|
+
envImportanceSampling = false,
|
|
67
|
+
diffuseNode = null,
|
|
68
|
+
binaryRefine = false
|
|
69
|
+
} = options;
|
|
70
|
+
|
|
71
|
+
let camera = options.camera ?? null;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* When `true`, the reflection direction is varied per pixel with stochastic GGX rays
|
|
75
|
+
* (second-generation SSR). When `false`, a single mirror reflection is traced and
|
|
76
|
+
* roughness is softened with a blur pass (first-generation SSR).
|
|
77
|
+
*
|
|
78
|
+
* @type {boolean}
|
|
79
|
+
*/
|
|
80
|
+
this.stochastic = stochastic;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* When `true`, env-luminance CDF tables are built and MIS is used for environment misses.
|
|
84
|
+
* Fixed at construction time.
|
|
85
|
+
*
|
|
86
|
+
* @type {boolean}
|
|
87
|
+
*/
|
|
88
|
+
this.envImportanceSampling = envImportanceSampling;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The node that represents the beauty pass.
|
|
92
|
+
*
|
|
93
|
+
* @type {Node<vec4>}
|
|
94
|
+
*/
|
|
95
|
+
this.colorNode = colorNode;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* A node that represents the scene's diffuse color (typically the MRT `diffuseColor` attachment).
|
|
99
|
+
* When `null`, the shader uses `vec3(1)`.
|
|
100
|
+
*
|
|
101
|
+
* @type {?Node<vec4>}
|
|
102
|
+
*/
|
|
103
|
+
this.diffuseNode = diffuseNode !== null ? nodeObject( diffuseNode ) : null;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* A node that represents the beauty pass's depth.
|
|
107
|
+
*
|
|
108
|
+
* @type {Node<float>}
|
|
109
|
+
*/
|
|
110
|
+
this.depthNode = depthNode;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* A node that represents the beauty pass's normals.
|
|
114
|
+
*
|
|
115
|
+
* @type {Node<vec3>}
|
|
116
|
+
*/
|
|
117
|
+
this.normalNode = normalNode;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Per-pixel metalness, used to drive the GGX reflection sampling and the non-metal
|
|
121
|
+
* early-out. When `null`, the shader treats surfaces as non-metallic.
|
|
122
|
+
*
|
|
123
|
+
* @type {?Node<float>}
|
|
124
|
+
*/
|
|
125
|
+
this.metalnessNode = metalnessNode;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Stochastic mode only: per-pixel normal-incidence reflectance (F0), typically an MRT
|
|
129
|
+
* `specularColorBlended` attachment, which already includes IOR, specular intensity and
|
|
130
|
+
* metalness (raw `material.specularColor` reflects too brightly). When `null`, F0 is
|
|
131
|
+
* derived from metalness and the diffuse color.
|
|
132
|
+
*
|
|
133
|
+
* @type {?Node<vec3>}
|
|
134
|
+
* @default null
|
|
135
|
+
*/
|
|
136
|
+
this.specularNode = specularNode;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Stochastic mode only: per-pixel grazing reflectance (F90), typically an MRT
|
|
140
|
+
* `specularF90` attachment. When `null`, the shader uses `1`.
|
|
141
|
+
*
|
|
142
|
+
* @type {?Node<float>}
|
|
143
|
+
* @default null
|
|
144
|
+
*/
|
|
145
|
+
this.specularF90Node = specularF90Node;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Per-pixel roughness, used to drive the GGX reflection sampling and the blur mip
|
|
149
|
+
* selection. When `null`, the shader treats surfaces as fully smooth.
|
|
150
|
+
*
|
|
151
|
+
* @type {?Node<float>}
|
|
152
|
+
*/
|
|
153
|
+
this.roughnessNode = roughnessNode;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Only used when {@link SSRNode#stochastic} is `false`. When `false`, non-metallic
|
|
157
|
+
* surfaces are discarded for a noticeable performance gain; set `true` to also
|
|
158
|
+
* reflect dielectrics. Baked into the shader as a compile-time constant; assigning a
|
|
159
|
+
* new value recompiles the SSR material.
|
|
160
|
+
*
|
|
161
|
+
* @type {boolean}
|
|
162
|
+
* @default false
|
|
163
|
+
*/
|
|
164
|
+
this._reflectNonMetals = reflectNonMetals;
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* The resolution scale. Valid values are in the range
|
|
168
|
+
* `[0,1]`. `1` means best quality but also results in
|
|
169
|
+
* more computational overhead. Setting to `0.5` means
|
|
170
|
+
* the effect is computed in half-resolution.
|
|
171
|
+
*
|
|
172
|
+
* @type {number}
|
|
173
|
+
* @default 1
|
|
174
|
+
*/
|
|
175
|
+
this.resolutionScale = 1;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* The `updateBeforeType` is set to `NodeUpdateType.FRAME` since the node renders
|
|
179
|
+
* its effect once per frame in `updateBefore()`.
|
|
180
|
+
*
|
|
181
|
+
* @type {string}
|
|
182
|
+
* @default 'frame'
|
|
183
|
+
*/
|
|
184
|
+
this.updateBeforeType = NodeUpdateType.FRAME;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Controls how far a fragment can reflect. Increasing this value result in more
|
|
188
|
+
* computational overhead but also increases the reflection distance.
|
|
189
|
+
*
|
|
190
|
+
* @type {UniformNode<float>}
|
|
191
|
+
*/
|
|
192
|
+
this.maxDistance = uniform( 1 );
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Controls the cutoff between what counts as a possible reflection hit and what does not.
|
|
196
|
+
*
|
|
197
|
+
* @type {UniformNode<float>}
|
|
198
|
+
*/
|
|
199
|
+
this.thickness = uniform( 0.1 );
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* A multiplier for the overall reflection intensity. `1` leaves the
|
|
203
|
+
* reflections unchanged, lower values dim them and higher values boost them.
|
|
204
|
+
*
|
|
205
|
+
* @type {UniformNode<float>}
|
|
206
|
+
* @default 1
|
|
207
|
+
*/
|
|
208
|
+
this.intensity = uniform( 1 );
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Screen-edge fade width, in UV units. As a screen-space hit approaches a screen
|
|
212
|
+
* border, the reflection is faded over this distance — either toward the environment
|
|
213
|
+
* reflection ({@link SSRNode#screenEdgeFadeBlack} `false`) or to zero intensity
|
|
214
|
+
* (`true`). `0` disables it.
|
|
215
|
+
*
|
|
216
|
+
* @type {UniformNode<float>}
|
|
217
|
+
* @default 0.2
|
|
218
|
+
*/
|
|
219
|
+
this.screenEdgeFade = uniform( 0.2 );
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* When `true`, SSR fades to zero near screen borders instead of blending toward
|
|
223
|
+
* the environment map. Hits are faded by the reflection sample UV; misses are
|
|
224
|
+
* faded by the surface pixel UV.
|
|
225
|
+
*
|
|
226
|
+
* Baked into the shader as a compile-time constant so the unused fade branch is
|
|
227
|
+
* eliminated; assigning a new value recompiles the SSR material.
|
|
228
|
+
*
|
|
229
|
+
* @type {boolean}
|
|
230
|
+
* @default false
|
|
231
|
+
*/
|
|
232
|
+
this._screenEdgeFadeBlack = false;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Absolute env luminance cap. HDR env samples above this are scaled down (hue preserved).
|
|
236
|
+
*
|
|
237
|
+
* @type {UniformNode<float>}
|
|
238
|
+
* @default 10
|
|
239
|
+
*/
|
|
240
|
+
this.maxLuminance = uniform( 10 );
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* This parameter controls how detailed the raymarching process works.
|
|
244
|
+
* The value ranges is `[0,1]` where `1` means best quality (the maximum number
|
|
245
|
+
* of raymarching iterations/samples) and `0` means no samples at all.
|
|
246
|
+
*
|
|
247
|
+
* A quality of `0.5` is usually sufficient for most use cases. Try to keep
|
|
248
|
+
* this parameter as low as possible. Larger values result in noticeable more
|
|
249
|
+
* overhead.
|
|
250
|
+
*
|
|
251
|
+
* @type {UniformNode<float>}
|
|
252
|
+
*/
|
|
253
|
+
this.quality = uniform( 0.5 );
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Mirror bias for the stochastic GGX sampling. Concentrates the reflected rays toward
|
|
257
|
+
* the lobe's narrow (near-mirror) core, trading sampling bias for less noise.
|
|
258
|
+
* `0` samples the full VNDF lobe; values toward `1` tighten the cone. Range `[0,1]`.
|
|
259
|
+
*
|
|
260
|
+
* @type {UniformNode<float>}
|
|
261
|
+
* @default 0
|
|
262
|
+
*/
|
|
263
|
+
this.mirrorBias = uniform( 0 );
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* The quality of the blur. Must be an integer in the range `[1,3]`.
|
|
267
|
+
*
|
|
268
|
+
* Baked into the blur shader as a compile-time constant so the `(size*2+1)²`
|
|
269
|
+
* sample loop unrolls; assigning a new value recompiles the blur material.
|
|
270
|
+
*
|
|
271
|
+
* @type {number}
|
|
272
|
+
* @default 2
|
|
273
|
+
*/
|
|
274
|
+
this._blurQuality = 2;
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Enables sub-step binary-search refinement of a detected hit. When on, a coarse
|
|
278
|
+
* crossing is bisected toward the exact intersection (sharper hits, less step
|
|
279
|
+
* aliasing) at the cost of extra depth samples. Baked into the shader as a
|
|
280
|
+
* compile-time constant; assigning a new value rebuilds the SSR material.
|
|
281
|
+
*
|
|
282
|
+
* @type {boolean}
|
|
283
|
+
* @default false
|
|
284
|
+
*/
|
|
285
|
+
this._binaryRefine = binaryRefine;
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Non-linear step distribution exponent. `1` = uniform steps; `> 1` concentrates
|
|
289
|
+
* samples near the ray origin — where most short-range reflections are missed — and
|
|
290
|
+
* spaces them out toward maxDistance, as `s = (i / steps) ^ stepExponent`.
|
|
291
|
+
*
|
|
292
|
+
* Baked into the shader as a compile-time constant so `pow()` folds to a few
|
|
293
|
+
* multiplies; assigning a new value recompiles the SSR material. Only used by the
|
|
294
|
+
* stochastic reflection path.
|
|
295
|
+
*
|
|
296
|
+
* @type {number}
|
|
297
|
+
* @default 2
|
|
298
|
+
*/
|
|
299
|
+
this._stepExponent = 2;
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* HDR environment map for screen-space misses.
|
|
303
|
+
*
|
|
304
|
+
* @type {?Texture}
|
|
305
|
+
*/
|
|
306
|
+
this.environmentNode = environmentNode;
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* A node that represents the history texture for multi-bounce reflections.
|
|
310
|
+
*
|
|
311
|
+
* @type {?Texture}
|
|
312
|
+
*/
|
|
313
|
+
this.historyTexture = null;
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* A node that represents the velocity texture for reprojection.
|
|
317
|
+
*
|
|
318
|
+
* @type {?Node<vec2>}
|
|
319
|
+
*/
|
|
320
|
+
this.velocityTexture = null;
|
|
321
|
+
|
|
322
|
+
//
|
|
323
|
+
|
|
324
|
+
if ( camera === null ) {
|
|
325
|
+
|
|
326
|
+
if ( this.colorNode.passNode && this.colorNode.passNode.isPassNode === true ) {
|
|
327
|
+
|
|
328
|
+
camera = this.colorNode.passNode.camera;
|
|
329
|
+
|
|
330
|
+
} else {
|
|
331
|
+
|
|
332
|
+
throw new Error( 'THREE.SSRNode: No camera found. ssr() requires a camera.' );
|
|
333
|
+
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* The camera the scene is rendered with.
|
|
340
|
+
*
|
|
341
|
+
* @type {Camera}
|
|
342
|
+
*/
|
|
343
|
+
this.camera = camera;
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* The spread of the blur. Automatically set when generating mips.
|
|
347
|
+
*
|
|
348
|
+
* @private
|
|
349
|
+
* @type {UniformNode<int>}
|
|
350
|
+
*/
|
|
351
|
+
this._blurSpread = uniform( 1 );
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Represents the projection matrix of the scene's camera.
|
|
355
|
+
*
|
|
356
|
+
* @private
|
|
357
|
+
* @type {UniformNode<mat4>}
|
|
358
|
+
*/
|
|
359
|
+
this._cameraProjectionMatrix = uniform( camera.projectionMatrix );
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Represents the inverse projection matrix of the scene's camera.
|
|
363
|
+
*
|
|
364
|
+
* @private
|
|
365
|
+
* @type {UniformNode<mat4>}
|
|
366
|
+
*/
|
|
367
|
+
this._cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse );
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Represents the near value of the scene's camera.
|
|
371
|
+
*
|
|
372
|
+
* @private
|
|
373
|
+
* @type {ReferenceNode<float>}
|
|
374
|
+
*/
|
|
375
|
+
this._cameraNear = reference( 'near', 'float', camera );
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Represents the far value of the scene's camera.
|
|
379
|
+
*
|
|
380
|
+
* @private
|
|
381
|
+
* @type {ReferenceNode<float>}
|
|
382
|
+
*/
|
|
383
|
+
this._cameraFar = reference( 'far', 'float', camera );
|
|
384
|
+
|
|
385
|
+
this._cameraWorldMatrix = uniform( new Matrix4().copy( camera.matrixWorld ) );
|
|
386
|
+
this._cameraWorldPosition = uniform( new Vector3().copy( camera.position ) );
|
|
387
|
+
|
|
388
|
+
this._cameraViewMatrix = uniform( new Matrix4().copy( camera.matrixWorld ) );
|
|
389
|
+
this._cameraViewMatrixInverse = uniform( new Matrix4().copy( camera.matrixWorldInverse ) );
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* The resolution of the pass.
|
|
393
|
+
*
|
|
394
|
+
* @private
|
|
395
|
+
* @type {UniformNode<vec2>}
|
|
396
|
+
*/
|
|
397
|
+
this._resolution = uniform( new Vector2() );
|
|
398
|
+
|
|
399
|
+
this._noiseIndex = uniform( 0 );
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* CDF-backed environment sampler. Created when {@link setEnvMap} is called.
|
|
403
|
+
*
|
|
404
|
+
* @private
|
|
405
|
+
* @type {?ImportanceSampledEnvironment}
|
|
406
|
+
*/
|
|
407
|
+
this._importanceEnvironment = null;
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Intensity multiplier applied to environment-map reflections on screen-space
|
|
411
|
+
* misses and at screen edges. Defaults to π to match the former hardcoded multiplier.
|
|
412
|
+
*
|
|
413
|
+
* @type {UniformNode<float>}
|
|
414
|
+
* @default Math.PI
|
|
415
|
+
*/
|
|
416
|
+
this.environmentIntensity = uniform( Math.PI );
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* The render target the SSR is rendered into.
|
|
420
|
+
*
|
|
421
|
+
* @private
|
|
422
|
+
* @type {RenderTarget}
|
|
423
|
+
*/
|
|
424
|
+
this._ssrRenderTarget = new RenderTarget( 1, 1, { depthBuffer: false, type: HalfFloatType } );
|
|
425
|
+
this._ssrRenderTarget.texture.name = 'SSRNode.SSR';
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* The render target for the blurred SSR reflections.
|
|
429
|
+
*
|
|
430
|
+
* @private
|
|
431
|
+
* @type {RenderTarget}
|
|
432
|
+
*/
|
|
433
|
+
this._blurRenderTarget = new RenderTarget( 1, 1, { depthBuffer: false, type: HalfFloatType, minFilter: LinearMipmapLinearFilter, magFilter: LinearFilter } );
|
|
434
|
+
this._blurRenderTarget.texture.name = 'SSRNode.Blur';
|
|
435
|
+
this._blurRenderTarget.texture.mipmaps.push( {}, {}, {}, {}, {} );
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* The material that is used to render the effect.
|
|
439
|
+
*
|
|
440
|
+
* @private
|
|
441
|
+
* @type {NodeMaterial}
|
|
442
|
+
*/
|
|
443
|
+
this._ssrMaterial = new NodeMaterial();
|
|
444
|
+
this._ssrMaterial.name = 'SSRNode.SSR';
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* The SSR fragment `Fn` and its shared context, captured in {@link SSRNode#setup}.
|
|
448
|
+
* Re-invoking the `Fn` produces a fresh node graph, which is how the baked
|
|
449
|
+
* compile-time constants are re-applied when they change (see {@link SSRNode#_buildSSRMaterial}).
|
|
450
|
+
*
|
|
451
|
+
* @private
|
|
452
|
+
*/
|
|
453
|
+
this._ssrFn = null;
|
|
454
|
+
this._sharedContext = null;
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* The blur material.
|
|
458
|
+
*
|
|
459
|
+
* @private
|
|
460
|
+
* @type {NodeMaterial}
|
|
461
|
+
*/
|
|
462
|
+
this._blurMaterial = new NodeMaterial();
|
|
463
|
+
this._blurMaterial.name = 'SSRNode.Blur';
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* The copy material.
|
|
467
|
+
*
|
|
468
|
+
* @private
|
|
469
|
+
* @type {NodeMaterial}
|
|
470
|
+
*/
|
|
471
|
+
this._copyMaterial = new NodeMaterial();
|
|
472
|
+
this._copyMaterial.name = 'SSRNode.Copy';
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* The result of the effect is represented as a separate texture node.
|
|
476
|
+
*
|
|
477
|
+
* @private
|
|
478
|
+
* @type {PassTextureNode}
|
|
479
|
+
*/
|
|
480
|
+
this._textureNode = passTexture( this, this._ssrRenderTarget.texture );
|
|
481
|
+
|
|
482
|
+
let blurredTextureNode = null;
|
|
483
|
+
|
|
484
|
+
if ( this.stochastic === false && this.roughnessNode !== null ) {
|
|
485
|
+
|
|
486
|
+
const mips = this._blurRenderTarget.texture.mipmaps.length - 1;
|
|
487
|
+
const r = this.roughnessNode;
|
|
488
|
+
const lod = r.mul( r ).mul( mips ).clamp( 0, mips );
|
|
489
|
+
|
|
490
|
+
blurredTextureNode = passTexture( this, this._blurRenderTarget.texture ).level( lod );
|
|
491
|
+
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Holds the blurred SSR reflections.
|
|
496
|
+
*
|
|
497
|
+
* @private
|
|
498
|
+
* @type {?PassTextureNode}
|
|
499
|
+
*/
|
|
500
|
+
this._blurredTextureNode = blurredTextureNode;
|
|
501
|
+
|
|
502
|
+
if ( environmentNode !== null && environmentNode.isTexture === true ) {
|
|
503
|
+
|
|
504
|
+
this.setEnvMap( environmentNode );
|
|
505
|
+
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Non-linear step distribution exponent (compile-time constant). See the backing
|
|
512
|
+
* field for details. Assigning a new value recompiles the SSR material.
|
|
513
|
+
*
|
|
514
|
+
* @type {number}
|
|
515
|
+
*/
|
|
516
|
+
get stepExponent() {
|
|
517
|
+
|
|
518
|
+
return this._stepExponent;
|
|
519
|
+
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
set stepExponent( value ) {
|
|
523
|
+
|
|
524
|
+
if ( value !== this._stepExponent ) {
|
|
525
|
+
|
|
526
|
+
this._stepExponent = value;
|
|
527
|
+
this._buildSSRMaterial();
|
|
528
|
+
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Blur kernel size (compile-time constant). Assigning a new value recompiles the
|
|
535
|
+
* blur material.
|
|
536
|
+
*
|
|
537
|
+
* @type {number}
|
|
538
|
+
*/
|
|
539
|
+
get blurQuality() {
|
|
540
|
+
|
|
541
|
+
return this._blurQuality;
|
|
542
|
+
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
set blurQuality( value ) {
|
|
546
|
+
|
|
547
|
+
if ( value !== this._blurQuality ) {
|
|
548
|
+
|
|
549
|
+
this._blurQuality = value;
|
|
550
|
+
|
|
551
|
+
// The size is baked into the boxBlur node tree, so rebuild it (recompiles the material).
|
|
552
|
+
if ( this.stochastic === false ) this._buildBlurMaterial();
|
|
553
|
+
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Builds (or rebuilds) the blur material's node graph, baking the current
|
|
560
|
+
* {@link SSRNode#blurQuality} as the kernel size so the sample loop unrolls.
|
|
561
|
+
*
|
|
562
|
+
* @private
|
|
563
|
+
*/
|
|
564
|
+
_buildBlurMaterial() {
|
|
565
|
+
|
|
566
|
+
this._blurMaterial.fragmentNode = boxBlur( texture( this._ssrRenderTarget.texture ), { size: this._blurQuality, separation: this._blurSpread } );
|
|
567
|
+
this._blurMaterial.needsUpdate = true;
|
|
568
|
+
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Whether SSR fades to black near screen borders (compile-time constant). Assigning
|
|
573
|
+
* a new value recompiles the SSR material.
|
|
574
|
+
*
|
|
575
|
+
* @type {boolean}
|
|
576
|
+
*/
|
|
577
|
+
get screenEdgeFadeBlack() {
|
|
578
|
+
|
|
579
|
+
return this._screenEdgeFadeBlack;
|
|
580
|
+
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
set screenEdgeFadeBlack( value ) {
|
|
584
|
+
|
|
585
|
+
if ( value !== this._screenEdgeFadeBlack ) {
|
|
586
|
+
|
|
587
|
+
this._screenEdgeFadeBlack = value;
|
|
588
|
+
this._buildSSRMaterial();
|
|
589
|
+
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Whether sub-step binary-search hit refinement is enabled (compile-time constant).
|
|
596
|
+
* Assigning a new value rebuilds the SSR material.
|
|
597
|
+
*
|
|
598
|
+
* @type {boolean}
|
|
599
|
+
*/
|
|
600
|
+
get binaryRefine() {
|
|
601
|
+
|
|
602
|
+
return this._binaryRefine;
|
|
603
|
+
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
set binaryRefine( value ) {
|
|
607
|
+
|
|
608
|
+
if ( value !== this._binaryRefine ) {
|
|
609
|
+
|
|
610
|
+
this._binaryRefine = value;
|
|
611
|
+
this._buildSSRMaterial();
|
|
612
|
+
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Whether dielectrics are reflected in the non-stochastic path (compile-time constant).
|
|
619
|
+
* Assigning a new value rebuilds the SSR material.
|
|
620
|
+
*
|
|
621
|
+
* @type {boolean}
|
|
622
|
+
*/
|
|
623
|
+
get reflectNonMetals() {
|
|
624
|
+
|
|
625
|
+
return this._reflectNonMetals;
|
|
626
|
+
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
set reflectNonMetals( value ) {
|
|
630
|
+
|
|
631
|
+
if ( value !== this._reflectNonMetals ) {
|
|
632
|
+
|
|
633
|
+
this._reflectNonMetals = value;
|
|
634
|
+
this._buildSSRMaterial();
|
|
635
|
+
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* Rebuilds the SSR material's node graph by re-invoking the fragment `Fn`, which
|
|
642
|
+
* re-bakes the compile-time constants ({@link SSRNode#binaryRefine},
|
|
643
|
+
* {@link SSRNode#stepExponent}, {@link SSRNode#screenEdgeFadeBlack}) at their current
|
|
644
|
+
* values. A no-op until {@link SSRNode#setup} has captured the `Fn`.
|
|
645
|
+
*
|
|
646
|
+
* @private
|
|
647
|
+
*/
|
|
648
|
+
_buildSSRMaterial() {
|
|
649
|
+
|
|
650
|
+
if ( this._ssrFn === null ) return;
|
|
651
|
+
|
|
652
|
+
this._ssrMaterial.contextNode = context( this._sharedContext );
|
|
653
|
+
this._ssrMaterial.fragmentNode = this._ssrFn();
|
|
654
|
+
this._ssrMaterial.needsUpdate = true;
|
|
655
|
+
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* Returns the result of the effect as a texture node.
|
|
660
|
+
*
|
|
661
|
+
* @return {PassTextureNode} A texture node that represents the result of the effect.
|
|
662
|
+
*/
|
|
663
|
+
getTextureNode() {
|
|
664
|
+
|
|
665
|
+
return ( this.stochastic === false && this.roughnessNode !== null ) ? this._blurredTextureNode : this._textureNode;
|
|
666
|
+
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Sets the size of the effect.
|
|
671
|
+
*
|
|
672
|
+
* @param {number} width - The width of the effect.
|
|
673
|
+
* @param {number} height - The height of the effect.
|
|
674
|
+
*/
|
|
675
|
+
setSize( width, height ) {
|
|
676
|
+
|
|
677
|
+
width = Math.round( this.resolutionScale * width );
|
|
678
|
+
height = Math.round( this.resolutionScale * height );
|
|
679
|
+
|
|
680
|
+
this._resolution.value.set( width, height );
|
|
681
|
+
this._ssrRenderTarget.setSize( width, height );
|
|
682
|
+
this._blurRenderTarget.setSize( width, height );
|
|
683
|
+
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Wires the feedback inputs for multi-bounce reflections: the previous frame's
|
|
688
|
+
* denoised result (`history`) and the velocity buffer used to reproject it
|
|
689
|
+
* (`velocity`). `history` accepts the producing node (e.g. a
|
|
690
|
+
* {@link RecurrentDenoiseNode}) — its output render target is used — or a raw
|
|
691
|
+
* texture. Pass `null` for both to disable multi-bounce.
|
|
692
|
+
*
|
|
693
|
+
* @param {Texture} history
|
|
694
|
+
* @param {Node<vec2>} velocity
|
|
695
|
+
*/
|
|
696
|
+
setHistory( history, velocity ) {
|
|
697
|
+
|
|
698
|
+
this.historyTexture = ( history && typeof history.getRenderTarget === 'function' )
|
|
699
|
+
? history.getRenderTarget().texture
|
|
700
|
+
: history;
|
|
701
|
+
this.velocityTexture = velocity;
|
|
702
|
+
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* Sets the environment map for importance-sampled env lighting when
|
|
707
|
+
* screen-space rays miss. Call this whenever the scene's env map changes.
|
|
708
|
+
*
|
|
709
|
+
* Uses {@link ImportanceSampledEnvironment} (CDF + MIS adapted from
|
|
710
|
+
* [three-gpu-pathtracer](https://github.com/gkjohnson/three-gpu-pathtracer)).
|
|
711
|
+
*
|
|
712
|
+
* @param {Texture|null} hdr - The equirectangular HDR environment map, or null to disable.
|
|
713
|
+
* @see {@link https://github.com/gkjohnson/three-gpu-pathtracer}
|
|
714
|
+
*/
|
|
715
|
+
setEnvMap( hdr ) {
|
|
716
|
+
|
|
717
|
+
if ( hdr === null ) {
|
|
718
|
+
|
|
719
|
+
if ( this._importanceEnvironment !== null ) {
|
|
720
|
+
|
|
721
|
+
this._importanceEnvironment.clear();
|
|
722
|
+
this._importanceEnvironment = null;
|
|
723
|
+
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
this._buildSSRMaterial();
|
|
727
|
+
return;
|
|
728
|
+
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
if ( hdr.image === undefined || hdr.image.data === undefined ) {
|
|
732
|
+
|
|
733
|
+
console.warn( 'SSRNode: `environmentNode` / `setEnvMap()` expects an equirectangular HDR texture with CPU-side image data (e.g. RGBELoader). PMREM cubemaps and `scene.environment` are not supported.' );
|
|
734
|
+
return;
|
|
735
|
+
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
if ( this._importanceEnvironment === null ) {
|
|
739
|
+
|
|
740
|
+
this._importanceEnvironment = new ImportanceSampledEnvironment( this.envImportanceSampling );
|
|
741
|
+
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
this._importanceEnvironment.updateFrom( hdr );
|
|
745
|
+
this._buildSSRMaterial();
|
|
746
|
+
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Intensity multiplier for the importance-sampled env contribution.
|
|
751
|
+
* Only available after {@link setEnvMap} has been called.
|
|
752
|
+
*
|
|
753
|
+
* @type {?UniformNode<float>}
|
|
754
|
+
*/
|
|
755
|
+
get envMapIntensity() {
|
|
756
|
+
|
|
757
|
+
return this._importanceEnvironment !== null ? this._importanceEnvironment.intensity : null;
|
|
758
|
+
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* This method is used to render the effect once per frame.
|
|
763
|
+
*
|
|
764
|
+
* @param {NodeFrame} frame - The current node frame.
|
|
765
|
+
*/
|
|
766
|
+
updateBefore( frame ) {
|
|
767
|
+
|
|
768
|
+
const { renderer } = frame;
|
|
769
|
+
|
|
770
|
+
this._cameraWorldMatrix.value.copy( this.camera.matrixWorld );
|
|
771
|
+
this._cameraWorldPosition.value.copy( this.camera.position );
|
|
772
|
+
|
|
773
|
+
_rendererState = RendererUtils.resetRendererState( renderer, _rendererState );
|
|
774
|
+
|
|
775
|
+
const ssrRenderTarget = this._ssrRenderTarget;
|
|
776
|
+
const blurRenderTarget = this._blurRenderTarget;
|
|
777
|
+
|
|
778
|
+
const size = renderer.getDrawingBufferSize( _size );
|
|
779
|
+
|
|
780
|
+
_quadMesh.material = this._ssrMaterial;
|
|
781
|
+
|
|
782
|
+
this.setSize( size.width, size.height );
|
|
783
|
+
|
|
784
|
+
// Advance the noise index once per frame (matches SSGI / Denoise).
|
|
785
|
+
this._noiseIndex.value = ( this._noiseIndex.value + 1 ) % 0x7fffffff;
|
|
786
|
+
|
|
787
|
+
// clear
|
|
788
|
+
|
|
789
|
+
renderer.setMRT( null );
|
|
790
|
+
renderer.setClearColor( 0x000000, 0 );
|
|
791
|
+
|
|
792
|
+
// ssr
|
|
793
|
+
|
|
794
|
+
renderer.setRenderTarget( ssrRenderTarget );
|
|
795
|
+
_quadMesh.name = 'SSR [ Reflections ]';
|
|
796
|
+
_quadMesh.render( renderer );
|
|
797
|
+
|
|
798
|
+
// blur (optional)
|
|
799
|
+
|
|
800
|
+
if ( this.stochastic === false && this.roughnessNode !== null ) {
|
|
801
|
+
|
|
802
|
+
// blur mips but leave the base mip unblurred
|
|
803
|
+
|
|
804
|
+
for ( let i = 0; i < blurRenderTarget.texture.mipmaps.length; i ++ ) {
|
|
805
|
+
|
|
806
|
+
_quadMesh.material = ( i === 0 ) ? this._copyMaterial : this._blurMaterial;
|
|
807
|
+
|
|
808
|
+
this._blurSpread.value = i;
|
|
809
|
+
renderer.setRenderTarget( blurRenderTarget, 0, i );
|
|
810
|
+
_quadMesh.name = 'SSR [ Blur Level ' + i + ' ]';
|
|
811
|
+
_quadMesh.render( renderer );
|
|
812
|
+
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
// restore
|
|
818
|
+
|
|
819
|
+
RendererUtils.restoreRendererState( renderer, _rendererState );
|
|
820
|
+
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* This method is used to setup the effect's TSL code.
|
|
825
|
+
*
|
|
826
|
+
* @param {NodeBuilder} builder - The current node builder.
|
|
827
|
+
* @return {PassTextureNode}
|
|
828
|
+
*/
|
|
829
|
+
setup( builder ) {
|
|
830
|
+
|
|
831
|
+
const uvNode = uv();
|
|
832
|
+
|
|
833
|
+
const pointToLineDistance = Fn( ( [ point, linePointA, linePointB ] ) => {
|
|
834
|
+
|
|
835
|
+
// https://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
|
|
836
|
+
|
|
837
|
+
return cross( point.sub( linePointA ), point.sub( linePointB ) ).length().div( linePointB.sub( linePointA ).length() );
|
|
838
|
+
|
|
839
|
+
}, { point: 'vec3', linePointA: 'vec3', linePointB: 'vec3', return: 'float' } );
|
|
840
|
+
|
|
841
|
+
const pointPlaneDistance = Fn( ( [ point, planePoint, planeNormal ] ) => {
|
|
842
|
+
|
|
843
|
+
// https://mathworld.wolfram.com/Point-PlaneDistance.html
|
|
844
|
+
// https://en.wikipedia.org/wiki/Plane_(geometry)
|
|
845
|
+
// http://paulbourke.net/geometry/pointlineplane/
|
|
846
|
+
|
|
847
|
+
// planeNormal is already normalized, so the denominator is 1.
|
|
848
|
+
const d = mul( planeNormal.x, planePoint.x ).add( mul( planeNormal.y, planePoint.y ) ).add( mul( planeNormal.z, planePoint.z ) ).negate().toVar();
|
|
849
|
+
const distance = mul( planeNormal.x, point.x ).add( mul( planeNormal.y, point.y ) ).add( mul( planeNormal.z, point.z ) ).add( d );
|
|
850
|
+
return distance;
|
|
851
|
+
|
|
852
|
+
}, { point: 'vec3', planePoint: 'vec3', planeNormal: 'vec3', return: 'float' } );
|
|
853
|
+
|
|
854
|
+
const getViewZ = Fn( ( [ depth ] ) => {
|
|
855
|
+
|
|
856
|
+
let viewZNode;
|
|
857
|
+
|
|
858
|
+
if ( this.camera.isPerspectiveCamera ) {
|
|
859
|
+
|
|
860
|
+
viewZNode = perspectiveDepthToViewZ( depth, this._cameraNear, this._cameraFar );
|
|
861
|
+
|
|
862
|
+
} else {
|
|
863
|
+
|
|
864
|
+
viewZNode = orthographicDepthToViewZ( depth, this._cameraNear, this._cameraFar );
|
|
865
|
+
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
return viewZNode;
|
|
869
|
+
|
|
870
|
+
} );
|
|
871
|
+
|
|
872
|
+
const sampleDepth = ( uv ) => projectionDepth( this.depthNode.sample( uv ).r, this._cameraNear, this._cameraFar );
|
|
873
|
+
|
|
874
|
+
const sampleMarchNoise = this.stochastic === true ? bindAnalyticNoise( this._resolution, 47 ) : null;
|
|
875
|
+
|
|
876
|
+
const computeScreenBorderFactor = Fn( ( [ uvCoord, borderWidth ] ) => {
|
|
877
|
+
|
|
878
|
+
const border = borderWidth.max( 1e-4 );
|
|
879
|
+
|
|
880
|
+
// Distance to the nearest screen edge — uniform falloff at corners.
|
|
881
|
+
const edgeDist = min(
|
|
882
|
+
min( uvCoord.x, float( 1 ).sub( uvCoord.x ) ),
|
|
883
|
+
min( uvCoord.y, float( 1 ).sub( uvCoord.y ) )
|
|
884
|
+
);
|
|
885
|
+
|
|
886
|
+
// Two smoothsteps for a softer ease-in-out than a single ramp.
|
|
887
|
+
const t = edgeDist.smoothstep( 0, border );
|
|
888
|
+
|
|
889
|
+
return t.smoothstep( 0, 1 ).pow( 0.125 );
|
|
890
|
+
|
|
891
|
+
}, { uvCoord: 'vec2', borderWidth: 'float', return: 'float' } );
|
|
892
|
+
|
|
893
|
+
const ssr = Fn( () => {
|
|
894
|
+
|
|
895
|
+
const noise = this.stochastic === true ? sampleMarchNoise( uvNode, this._noiseIndex ) : null;
|
|
896
|
+
// reconstruct at the depth texel center
|
|
897
|
+
|
|
898
|
+
const depthSize = vec2( textureSize( this.depthNode ) ).toConst();
|
|
899
|
+
const uvPos = uvNode.mul( depthSize ).floor().add( 0.5 ).div( depthSize ).toVar();
|
|
900
|
+
|
|
901
|
+
const depth = sampleDepth( uvPos ).toVar();
|
|
902
|
+
|
|
903
|
+
// Skip background pixels (cleared far-plane depth); the target is cleared each frame.
|
|
904
|
+
isBackgroundDepth( depth ).discard();
|
|
905
|
+
|
|
906
|
+
const viewPosition = getViewPosition( uvPos, depth, this._cameraProjectionMatrixInverse ).toVar();
|
|
907
|
+
const worldPosition = this._cameraWorldMatrix.mul( vec4( viewPosition, 1.0 ) ).xyz.toVar();
|
|
908
|
+
const viewNormal = this.normalNode.rgb.normalize().toVar();
|
|
909
|
+
|
|
910
|
+
const viewIncidentDir = ( ( this.camera.isPerspectiveCamera ) ? normalize( viewPosition ) : vec3( 0, 0, - 1 ) ).toVar();
|
|
911
|
+
|
|
912
|
+
// The node system samples the metalness/roughness textures at the current uv,
|
|
913
|
+
// so no explicit sample() is needed here.
|
|
914
|
+
const metalness = float( this.metalnessNode );
|
|
915
|
+
|
|
916
|
+
if ( this.stochastic === false && this._reflectNonMetals === false ) {
|
|
917
|
+
|
|
918
|
+
metalness.lessThanEqual( 0.0 ).discard();
|
|
919
|
+
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
const roughness = float( this.roughnessNode );
|
|
923
|
+
const glossiness = min( roughness.div( 0.25 ), 1 ).oneMinus();
|
|
924
|
+
// Only the fade-to-black miss path reads this, and that path is baked out otherwise.
|
|
925
|
+
const surfaceBorderFactor = this.screenEdgeFadeBlack ? computeScreenBorderFactor( uvPos, this.screenEdgeFade ) : null;
|
|
926
|
+
const hitBorderWidth = this.screenEdgeFade.mul( glossiness );
|
|
927
|
+
|
|
928
|
+
const V = viewIncidentDir.negate().normalize().toVar();
|
|
929
|
+
|
|
930
|
+
let viewReflectDir, finalSampleWeight, specDominantFactor;
|
|
931
|
+
let sampleEnvReflection = null;
|
|
932
|
+
|
|
933
|
+
if ( this.stochastic === false ) {
|
|
934
|
+
|
|
935
|
+
viewReflectDir = reflect( viewIncidentDir, viewNormal ).normalize().toVar();
|
|
936
|
+
finalSampleWeight = vec3( metalness );
|
|
937
|
+
specDominantFactor = float( 1 );
|
|
938
|
+
|
|
939
|
+
} else {
|
|
940
|
+
|
|
941
|
+
const Xi = noise.toVar();
|
|
942
|
+
// mirror bias trades the unbiased GGX lobe for lower variance
|
|
943
|
+
Xi.y.assign( mix( Xi.y, 0.0, this.mirrorBias.mul( Xi.w.sqrt() ) ) );
|
|
944
|
+
|
|
945
|
+
// The base color only feeds the metalness F0 fallback.
|
|
946
|
+
const albedo = ( this.specularNode === null && this.diffuseNode !== null ? this.diffuseNode.sample( uvPos ).rgb : vec3( 1 ) ).toVar();
|
|
947
|
+
const ggxSample = ggxReflectionSample( viewNormal, V, roughness, metalness, albedo, Xi, this.specularNode, this.specularF90Node ?? 1 ).toVar();
|
|
948
|
+
|
|
949
|
+
// Sometimes the GGX sample is facing away from the surface, so we need to re-sample.
|
|
950
|
+
If( ggxSample.get( 'reflectDir' ).dot( viewNormal ).lessThan( 0 ), () => {
|
|
951
|
+
|
|
952
|
+
ggxSample.assign( ggxReflectionSample( viewNormal, V, roughness, metalness, albedo, Xi.add( Xi.mul( 7 ) ).fract(), this.specularNode, this.specularF90Node ?? 1 ) );
|
|
953
|
+
|
|
954
|
+
} );
|
|
955
|
+
|
|
956
|
+
viewReflectDir = ggxSample.get( 'reflectDir' ).toVar();
|
|
957
|
+
finalSampleWeight = ggxSample.get( 'sampleWeight' ).toVar();
|
|
958
|
+
specDominantFactor = getSpecularDominantFactor( ggxSample.get( 'NdotV' ), roughness ).toVar();
|
|
959
|
+
|
|
960
|
+
sampleEnvReflection = () => {
|
|
961
|
+
|
|
962
|
+
if ( this._importanceEnvironment === null ) return vec3( 0 );
|
|
963
|
+
|
|
964
|
+
const envColor = vec3( 0 ).toVar();
|
|
965
|
+
|
|
966
|
+
if ( this.envImportanceSampling ) {
|
|
967
|
+
|
|
968
|
+
const Xi2 = bindAnalyticNoise( this._resolution, 59 )( uvPos, this._noiseIndex );
|
|
969
|
+
|
|
970
|
+
envColor.assign( this._importanceEnvironment.sampleEnvironmentMIS( {
|
|
971
|
+
cameraWorldMatrix: this._cameraWorldMatrix,
|
|
972
|
+
viewReflectDir,
|
|
973
|
+
N: viewNormal,
|
|
974
|
+
V,
|
|
975
|
+
alpha: ggxSample.get( 'alpha' ),
|
|
976
|
+
f0: ggxSample.get( 'f0' ),
|
|
977
|
+
f90: ggxSample.get( 'f90' ),
|
|
978
|
+
Xi2
|
|
979
|
+
} ) );
|
|
980
|
+
|
|
981
|
+
} else {
|
|
982
|
+
|
|
983
|
+
envColor.assign( this._importanceEnvironment.sampleEnvironmentBRDF( {
|
|
984
|
+
cameraWorldMatrix: this._cameraWorldMatrix,
|
|
985
|
+
viewReflectDir,
|
|
986
|
+
N: viewNormal,
|
|
987
|
+
V,
|
|
988
|
+
alpha: ggxSample.get( 'alpha' ),
|
|
989
|
+
f0: ggxSample.get( 'f0' ),
|
|
990
|
+
f90: ggxSample.get( 'f90' )
|
|
991
|
+
} ) );
|
|
992
|
+
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
return envColor;
|
|
996
|
+
|
|
997
|
+
};
|
|
998
|
+
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
// Multi-bounce: fold in the previous frame's reflection at the hit point, reprojected by its
|
|
1002
|
+
// own motion. The (1 - history.a) decay damps the feedback. No-op until both textures are set.
|
|
1003
|
+
const reprojectHitPointHistory = ( uvHit, color ) => {
|
|
1004
|
+
|
|
1005
|
+
if ( ! ( this.historyTexture && this.velocityTexture ) ) return color;
|
|
1006
|
+
|
|
1007
|
+
const velocity = this.velocityTexture.sample( uvHit ).xy;
|
|
1008
|
+
const historyUV = uvHit.sub( velocity );
|
|
1009
|
+
const historyBounce = texture( this.historyTexture, historyUV ).toVar();
|
|
1010
|
+
const sampleDecay = historyBounce.a.oneMinus();
|
|
1011
|
+
|
|
1012
|
+
return color.add( historyBounce.rgb.mul( sampleDecay ) );
|
|
1013
|
+
|
|
1014
|
+
};
|
|
1015
|
+
|
|
1016
|
+
// Fades a screen-space hit near the screen borders, using the hit sample UV (where the
|
|
1017
|
+
// screen-space data was read). `screenEdgeFadeBlack` is baked, so the two modes branch in
|
|
1018
|
+
// JS: fade the reflection to black, or blend it toward the environment reflection.
|
|
1019
|
+
const applyHitEdgeFade = ( reflectColor, uvS, hitBorderWidth ) => {
|
|
1020
|
+
|
|
1021
|
+
if ( this.screenEdgeFadeBlack ) {
|
|
1022
|
+
|
|
1023
|
+
const hitBorderFactor = computeScreenBorderFactor( uvS, this.screenEdgeFade );
|
|
1024
|
+
reflectColor.rgb.mulAssign( hitBorderFactor );
|
|
1025
|
+
|
|
1026
|
+
} else {
|
|
1027
|
+
|
|
1028
|
+
const hitBorderFactor = computeScreenBorderFactor( uvS, hitBorderWidth );
|
|
1029
|
+
|
|
1030
|
+
If( hitBorderFactor.lessThan( 1 ), () => {
|
|
1031
|
+
|
|
1032
|
+
reflectColor.rgb.assign( mix( sampleEnvReflection().mul( this.environmentIntensity ), reflectColor.rgb, hitBorderFactor ) );
|
|
1033
|
+
|
|
1034
|
+
} );
|
|
1035
|
+
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
};
|
|
1039
|
+
|
|
1040
|
+
const maxReflectRayLen = this.maxDistance.div( dot( viewIncidentDir.negate(), viewNormal ).max( 1e-4 ) ).toVar();
|
|
1041
|
+
|
|
1042
|
+
const d1viewPosition = viewPosition.add( viewReflectDir.mul( maxReflectRayLen ) ).toVar();
|
|
1043
|
+
|
|
1044
|
+
// Camera type is fixed at build time, so guard the near-plane clamp with a JS branch
|
|
1045
|
+
// rather than a runtime uniform (the orthographic case compiles it out entirely).
|
|
1046
|
+
if ( this.camera.isPerspectiveCamera ) {
|
|
1047
|
+
|
|
1048
|
+
If( d1viewPosition.z.greaterThan( this._cameraNear.negate() ), () => {
|
|
1049
|
+
|
|
1050
|
+
const t = sub( this._cameraNear.negate(), viewPosition.z ).div( viewReflectDir.z );
|
|
1051
|
+
d1viewPosition.assign( viewPosition.add( viewReflectDir.mul( t ) ) );
|
|
1052
|
+
|
|
1053
|
+
} );
|
|
1054
|
+
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
const d0 = uvPos.mul( this._resolution ).xy.toVar();
|
|
1058
|
+
const d1 = getScreenPosition( d1viewPosition, this._cameraProjectionMatrix ).mul( this._resolution ).toVar();
|
|
1059
|
+
|
|
1060
|
+
// clip the ray to the screen so all steps land on visible texels
|
|
1061
|
+
|
|
1062
|
+
const extent = d1.sub( d0 ).toVar();
|
|
1063
|
+
const exitT = vec2(
|
|
1064
|
+
extent.x.greaterThanEqual( 0 ).select( this._resolution.x.sub( d0.x ), d0.x ),
|
|
1065
|
+
extent.y.greaterThanEqual( 0 ).select( this._resolution.y.sub( d0.y ), d0.y )
|
|
1066
|
+
).div( extent.abs().max( 1e-6 ) );
|
|
1067
|
+
const clipT = min( exitT.x, exitT.y ).min( 1 ).toConst();
|
|
1068
|
+
|
|
1069
|
+
If( clipT.lessThan( 1 ), () => {
|
|
1070
|
+
|
|
1071
|
+
d1.assign( d0.add( extent.mul( clipT ) ) );
|
|
1072
|
+
d1viewPosition.assign( this.camera.isPerspectiveCamera
|
|
1073
|
+
? mix( viewPosition.div( viewPosition.z ), d1viewPosition.div( d1viewPosition.z ), clipT ).div( mix( viewPosition.z.reciprocal(), d1viewPosition.z.reciprocal(), clipT ) )
|
|
1074
|
+
: mix( viewPosition, d1viewPosition, clipT ) );
|
|
1075
|
+
|
|
1076
|
+
} );
|
|
1077
|
+
|
|
1078
|
+
const xLen = d1.x.sub( d0.x ).toVar();
|
|
1079
|
+
const yLen = d1.y.sub( d0.y ).toVar();
|
|
1080
|
+
|
|
1081
|
+
// dominant-axis ray length in texels (used for the per-step floor below)
|
|
1082
|
+
const rayLen = max( xLen.abs(), yLen.abs() ).max( 1 ).toVar();
|
|
1083
|
+
|
|
1084
|
+
// Blur traces a single mirror ray, so spend steps in proportion to the ray's screen-space
|
|
1085
|
+
// length (cheap for the short rays that dominate). Scatter needs a fixed, bounded count for
|
|
1086
|
+
// coherent stochastic sampling; each step then spans the whole ray as rayVec / totalStep.
|
|
1087
|
+
const totalStep = int( this.stochastic === false
|
|
1088
|
+
? trunc( max( abs( xLen ), abs( yLen ) ).mul( this.quality.clamp() ) ).max( int( 1 ) ).toConst()
|
|
1089
|
+
: this.quality.clamp().mul( MAX_STEPS ).max( float( 1 ) ) ).toConst();
|
|
1090
|
+
|
|
1091
|
+
const xSpan = xLen.div( totalStep ).toVar();
|
|
1092
|
+
const ySpan = yLen.div( totalStep ).toVar();
|
|
1093
|
+
|
|
1094
|
+
const stepVec = vec2( xSpan, ySpan ).toVar();
|
|
1095
|
+
const invResolution = vec2( float( 1 ), float( 1 ) ).div( this._resolution ).toVar();
|
|
1096
|
+
const uvPixelStepX = vec2( invResolution.x, float( 0 ) ).toVar();
|
|
1097
|
+
|
|
1098
|
+
const output = vec4( 0 ).toVar();
|
|
1099
|
+
const hit = float( 0 ).toVar();
|
|
1100
|
+
|
|
1101
|
+
// Reflected-ray view-space Z at ray parameter s ∈ [0,1] (linear in 1/z for perspective),
|
|
1102
|
+
// hoisted so the march and refinement evaluate it identically.
|
|
1103
|
+
const recipVPZ = float( 1 ).div( viewPosition.z ).toConst();
|
|
1104
|
+
const recipD1VPZ = float( 1 ).div( d1viewPosition.z ).toConst();
|
|
1105
|
+
|
|
1106
|
+
// Camera type is known at build time, so branch at compile time rather than via a runtime select.
|
|
1107
|
+
const reflectRayZAt = this.camera.isPerspectiveCamera
|
|
1108
|
+
? ( sVal ) => float( 1 ).div( recipVPZ.add( sVal.mul( recipD1VPZ.sub( recipVPZ ) ) ) )
|
|
1109
|
+
: ( sVal ) => viewPosition.z.add( sVal.mul( d1viewPosition.z.sub( viewPosition.z ) ) );
|
|
1110
|
+
|
|
1111
|
+
// view-space point on the reflected ray at s
|
|
1112
|
+
|
|
1113
|
+
const rayPointAt = this.camera.isPerspectiveCamera
|
|
1114
|
+
? ( sVal ) => mix( viewPosition.div( viewPosition.z ), d1viewPosition.div( d1viewPosition.z ), sVal ).mul( reflectRayZAt( sVal ) )
|
|
1115
|
+
: ( sVal ) => mix( viewPosition, d1viewPosition, sVal );
|
|
1116
|
+
|
|
1117
|
+
// Screen-space position along the ray for a given s ∈ [0,1].
|
|
1118
|
+
const screenPosAt = ( sVal ) => d0.add( stepVec.mul( sVal.mul( totalStep ) ) );
|
|
1119
|
+
|
|
1120
|
+
// Ray parameter s ∈ [0,1] for step `idx`. Blur marches uniformly (matching the original loop:
|
|
1121
|
+
// one ~texel step per iteration). Scatter uses an exponential remap `(idx/steps)^stepExponent`
|
|
1122
|
+
// that concentrates samples near the origin, floored to ≥1 texel/step; `jitter` dissolves banding.
|
|
1123
|
+
const sampleFraction = this.stochastic === false
|
|
1124
|
+
? ( idx ) => idx.div( totalStep )
|
|
1125
|
+
: ( idx ) => max(
|
|
1126
|
+
idx.add( noise.z.sub( 0.5 ) ).div( totalStep ).pow( this.stepExponent ),
|
|
1127
|
+
idx.div( rayLen )
|
|
1128
|
+
);
|
|
1129
|
+
|
|
1130
|
+
// Carry the hit out of the loop so refinement runs after the march, not nested inside it (a
|
|
1131
|
+
// loop-inside-a-loop tripped shader-compiler bugs on some drivers). hitSLo/hitSHi bracket s.
|
|
1132
|
+
const foundHit = bool( false ).toVar();
|
|
1133
|
+
const hitSLo = float( 0 ).toVar();
|
|
1134
|
+
const hitSHi = float( 0 ).toVar();
|
|
1135
|
+
// Carry the coarse hit's UV/depth to skip a redundant fetch when refinement is off.
|
|
1136
|
+
const hitUvS = vec2( 0 ).toVar();
|
|
1137
|
+
const hitD = float( 0 ).toVar();
|
|
1138
|
+
const previousS = float( 0 ).toVar();
|
|
1139
|
+
const previousInFront = bool( true ).toVar();
|
|
1140
|
+
const canRefine = bool( false ).toVar();
|
|
1141
|
+
|
|
1142
|
+
// March from d0 toward d1, looking for an intersection with the depth buffer.
|
|
1143
|
+
Loop( { start: int( 1 ), end: totalStep }, ( { i } ) => {
|
|
1144
|
+
|
|
1145
|
+
// Exponentially-distributed ray parameter, shared by the sample position and ray depth.
|
|
1146
|
+
const s = sampleFraction( float( i ) ).toVar();
|
|
1147
|
+
|
|
1148
|
+
If( s.greaterThan( 1 ), () => {
|
|
1149
|
+
|
|
1150
|
+
Break();
|
|
1151
|
+
|
|
1152
|
+
} );
|
|
1153
|
+
|
|
1154
|
+
const xy = screenPosAt( s ).toVar();
|
|
1155
|
+
|
|
1156
|
+
If( xy.x.lessThan( 0 ).or( xy.x.greaterThan( this._resolution.x ) ).or( xy.y.lessThan( 0 ) ).or( xy.y.greaterThan( this._resolution.y ) ), () => {
|
|
1157
|
+
|
|
1158
|
+
Break();
|
|
1159
|
+
|
|
1160
|
+
} );
|
|
1161
|
+
|
|
1162
|
+
const uvS = xy.mul( invResolution ).toVar();
|
|
1163
|
+
const d = sampleDepth( uvS ).toVar();
|
|
1164
|
+
const vZ = getViewZ( d ).toVar();
|
|
1165
|
+
|
|
1166
|
+
const viewReflectRayZ = reflectRayZAt( s ).toVar();
|
|
1167
|
+
|
|
1168
|
+
// Advance the previous sample before any Continue() so rejected samples still bound the next bracket.
|
|
1169
|
+
const lastS = previousS.toVar();
|
|
1170
|
+
const lastInFront = previousInFront.toVar();
|
|
1171
|
+
previousS.assign( s );
|
|
1172
|
+
previousInFront.assign( viewReflectRayZ.greaterThan( vZ ) );
|
|
1173
|
+
|
|
1174
|
+
If( isBackgroundDepth( d ).not().and( viewReflectRayZ.lessThanEqual( vZ ) ), () => {
|
|
1175
|
+
|
|
1176
|
+
// Depth crossing: ray went behind the depth buffer. Gate by thickness before stopping
|
|
1177
|
+
// so an occluder gap doesn't end the march prematurely.
|
|
1178
|
+
const vP = getViewPosition( uvS, d, this._cameraProjectionMatrixInverse ).toVar();
|
|
1179
|
+
const away = pointToLineDistance( vP, viewPosition, d1viewPosition ).toVar();
|
|
1180
|
+
|
|
1181
|
+
const uvNeighbor = uvS.add( uvPixelStepX ).toVar();
|
|
1182
|
+
const vPNeighbor = getViewPosition( uvNeighbor, d, this._cameraProjectionMatrixInverse ).toVar();
|
|
1183
|
+
const minThickness = vPNeighbor.x.sub( vP.x ).mul( 3 ).toVar();
|
|
1184
|
+
// Only refinement may use a wider coarse tolerance.
|
|
1185
|
+
|
|
1186
|
+
const stepLength = distance( rayPointAt( lastS ), rayPointAt( s ) );
|
|
1187
|
+
const tk = ( this.binaryRefine ? max( max( minThickness, this.thickness ), stepLength ) : max( minThickness, this.thickness ) ).toVar();
|
|
1188
|
+
|
|
1189
|
+
If( away.lessThanEqual( tk ), () => {
|
|
1190
|
+
|
|
1191
|
+
const vN = this.normalNode.sample( uvS ).rgb.normalize().toVar();
|
|
1192
|
+
|
|
1193
|
+
// the reflected ray is pointing towards the same side as the fragment's normal (current ray position),
|
|
1194
|
+
// which means it wouldn't reflect off the surface. The loop continues to the next step for the next ray sample.
|
|
1195
|
+
If( dot( viewReflectDir, vN ).greaterThanEqual( 0 ), () => {
|
|
1196
|
+
|
|
1197
|
+
Continue();
|
|
1198
|
+
|
|
1199
|
+
} );
|
|
1200
|
+
|
|
1201
|
+
if ( this.stochastic === false ) {
|
|
1202
|
+
|
|
1203
|
+
// this distance represents the depth of the intersection point between the reflected ray and the scene.
|
|
1204
|
+
const distance = pointPlaneDistance( vP, viewPosition, viewNormal ).toVar();
|
|
1205
|
+
|
|
1206
|
+
// Distance exceeding limit: The reflection is potentially too far away and
|
|
1207
|
+
// might not contribute significantly to the final color
|
|
1208
|
+
If( distance.greaterThan( this.maxDistance ), () => {
|
|
1209
|
+
|
|
1210
|
+
Break();
|
|
1211
|
+
|
|
1212
|
+
} );
|
|
1213
|
+
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
foundHit.assign( true );
|
|
1217
|
+
hitUvS.assign( uvS );
|
|
1218
|
+
hitD.assign( d );
|
|
1219
|
+
|
|
1220
|
+
if ( this.binaryRefine ) {
|
|
1221
|
+
|
|
1222
|
+
// refine only front-to-back crossings
|
|
1223
|
+
|
|
1224
|
+
canRefine.assign( lastInFront );
|
|
1225
|
+
hitSLo.assign( lastS );
|
|
1226
|
+
hitSHi.assign( s );
|
|
1227
|
+
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
Break();
|
|
1231
|
+
|
|
1232
|
+
|
|
1233
|
+
} );
|
|
1234
|
+
|
|
1235
|
+
} );
|
|
1236
|
+
|
|
1237
|
+
} );
|
|
1238
|
+
|
|
1239
|
+
If( foundHit, () => {
|
|
1240
|
+
|
|
1241
|
+
// Bisect the bracketed crossing toward the exact intersection. Run after the march, not
|
|
1242
|
+
// nested (a loop-inside-a-loop tripped shader-compiler bugs on some drivers).
|
|
1243
|
+
if ( this.binaryRefine ) {
|
|
1244
|
+
|
|
1245
|
+
If( canRefine, () => {
|
|
1246
|
+
|
|
1247
|
+
Loop( { start: int( 0 ), end: int( 8 ), type: 'int', condition: '<' }, () => {
|
|
1248
|
+
|
|
1249
|
+
const sMid = hitSLo.add( hitSHi ).mul( 0.5 ).toVar();
|
|
1250
|
+
const uvMid = screenPosAt( sMid ).mul( invResolution ).toConst();
|
|
1251
|
+
const sceneZMid = getViewZ( sampleDepth( uvMid ) );
|
|
1252
|
+
const frontFacing = dot( viewReflectDir, this.normalNode.sample( uvMid ).rgb.normalize() ).lessThan( 0 );
|
|
1253
|
+
|
|
1254
|
+
If( reflectRayZAt( sMid ).lessThanEqual( sceneZMid ).and( frontFacing ), () => {
|
|
1255
|
+
|
|
1256
|
+
hitSHi.assign( sMid );
|
|
1257
|
+
|
|
1258
|
+
} ).Else( () => {
|
|
1259
|
+
|
|
1260
|
+
hitSLo.assign( sMid );
|
|
1261
|
+
|
|
1262
|
+
} );
|
|
1263
|
+
|
|
1264
|
+
} );
|
|
1265
|
+
|
|
1266
|
+
// re-fetch UV/depth at the refined `s`
|
|
1267
|
+
|
|
1268
|
+
hitUvS.assign( screenPosAt( hitSHi ).mul( invResolution ) );
|
|
1269
|
+
hitD.assign( sampleDepth( hitUvS ) );
|
|
1270
|
+
|
|
1271
|
+
} );
|
|
1272
|
+
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
// Shade the hit, reusing the depth fetched during the march (or refinement).
|
|
1276
|
+
const uvS = hitUvS;
|
|
1277
|
+
const vP = getViewPosition( uvS, hitD, this._cameraProjectionMatrixInverse ).toVar();
|
|
1278
|
+
|
|
1279
|
+
// In blur mode the ratio² falloff re-grows past maxDistance, so over-range hits fall back
|
|
1280
|
+
// to env. The scatter path bounds reach via ray length, so every hit shades.
|
|
1281
|
+
const distancePointPlane = this.stochastic === false ? pointPlaneDistance( vP, viewPosition, viewNormal ).toVar() : float( 0 );
|
|
1282
|
+
const withinRange = distancePointPlane.lessThanEqual( this.maxDistance ).toVar();
|
|
1283
|
+
|
|
1284
|
+
if ( this.binaryRefine ) {
|
|
1285
|
+
|
|
1286
|
+
// bisection can land on a depth discontinuity, so validate the refined hit
|
|
1287
|
+
|
|
1288
|
+
const neighbor = getViewPosition( uvS.add( uvPixelStepX ), hitD, this._cameraProjectionMatrixInverse );
|
|
1289
|
+
const tk = max( neighbor.x.sub( vP.x ).mul( 3 ), this.thickness );
|
|
1290
|
+
withinRange.assign( withinRange.and( isBackgroundDepth( hitD ).not() )
|
|
1291
|
+
.and( pointToLineDistance( vP, viewPosition, d1viewPosition ).lessThanEqual( tk ) ) );
|
|
1292
|
+
|
|
1293
|
+
withinRange.assign( withinRange.and( dot( viewReflectDir, this.normalNode.sample( uvS ).rgb.normalize() ).lessThan( 0 ) ) );
|
|
1294
|
+
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
If( withinRange, () => {
|
|
1298
|
+
|
|
1299
|
+
const hitWorldPosition = this._cameraWorldMatrix.mul( vec4( vP, 1.0 ) ).xyz.toVar();
|
|
1300
|
+
const worldDistance = distance( worldPosition, hitWorldPosition ).mul( specDominantFactor ).toVar();
|
|
1301
|
+
|
|
1302
|
+
const reflectColor = this.colorNode.sample( uvS ).toVar();
|
|
1303
|
+
|
|
1304
|
+
// Multi-bounce: add the reprojected previous-frame reflection at the hit point.
|
|
1305
|
+
reflectColor.rgb.assign( reprojectHitPointHistory( uvS, reflectColor.rgb ) );
|
|
1306
|
+
|
|
1307
|
+
if ( this.stochastic === true ) applyHitEdgeFade( reflectColor, uvS, hitBorderWidth );
|
|
1308
|
+
|
|
1309
|
+
// The scatter (GGX) path bakes distance/grazing response into finalSampleWeight.
|
|
1310
|
+
// The mirror/blur path is a plain reflection, so reapply upstream's squared
|
|
1311
|
+
// distance attenuation and grazing Fresnel here to match its falloff.
|
|
1312
|
+
let weightedColor = reflectColor.rgb.mul( finalSampleWeight );
|
|
1313
|
+
|
|
1314
|
+
if ( this.stochastic === false ) {
|
|
1315
|
+
|
|
1316
|
+
const ratio = float( 1 ).sub( distancePointPlane.div( this.maxDistance ) ).toVar();
|
|
1317
|
+
const attenuation = ratio.mul( ratio ).toVar();
|
|
1318
|
+
const fresnelCoe = div( dot( viewIncidentDir, viewReflectDir ).add( 1 ), 2 ).toVar();
|
|
1319
|
+
weightedColor = weightedColor.mul( attenuation.mul( fresnelCoe ) );
|
|
1320
|
+
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
hit.assign( 1 );
|
|
1324
|
+
output.assign( vec4( weightedColor, worldDistance ) );
|
|
1325
|
+
|
|
1326
|
+
} );
|
|
1327
|
+
|
|
1328
|
+
} );
|
|
1329
|
+
|
|
1330
|
+
// Screen-space ray missed: environment fallback (MIS when CDF env is set up).
|
|
1331
|
+
If( hit.equal( 0 ), () => {
|
|
1332
|
+
|
|
1333
|
+
if ( this.stochastic === true ) {
|
|
1334
|
+
|
|
1335
|
+
output.assign( vec4( sampleEnvReflection().mul( this.environmentIntensity ), float( ENV_RAY_LENGTH ) ) );
|
|
1336
|
+
|
|
1337
|
+
// Misses fade by the surface pixel UV (where the reflection is being shaded).
|
|
1338
|
+
if ( this.screenEdgeFadeBlack ) {
|
|
1339
|
+
|
|
1340
|
+
output.rgb.mulAssign( surfaceBorderFactor );
|
|
1341
|
+
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
} );
|
|
1347
|
+
|
|
1348
|
+
const lum = luminance( output.rgb ).max( 1e-4 ).toVar();
|
|
1349
|
+
output.rgb.mulAssign( this.maxLuminance.div( lum ).min( 1 ) );
|
|
1350
|
+
|
|
1351
|
+
// scale the reflection color by the user-controlled intensity
|
|
1352
|
+
output.rgb.mulAssign( this.intensity );
|
|
1353
|
+
|
|
1354
|
+
return output.max( 0 );
|
|
1355
|
+
|
|
1356
|
+
} );
|
|
1357
|
+
|
|
1358
|
+
|
|
1359
|
+
this._ssrFn = ssr;
|
|
1360
|
+
this._sharedContext = builder.getSharedContext();
|
|
1361
|
+
this._buildSSRMaterial();
|
|
1362
|
+
|
|
1363
|
+
const reflectionBuffer = texture( this._ssrRenderTarget.texture );
|
|
1364
|
+
|
|
1365
|
+
if ( this.stochastic === false ) {
|
|
1366
|
+
|
|
1367
|
+
this._buildBlurMaterial();
|
|
1368
|
+
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
this._copyMaterial.fragmentNode = reflectionBuffer;
|
|
1372
|
+
this._copyMaterial.needsUpdate = true;
|
|
1373
|
+
|
|
1374
|
+
//
|
|
1375
|
+
|
|
1376
|
+
return this.getTextureNode();
|
|
1377
|
+
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
getRenderTarget() {
|
|
1381
|
+
|
|
1382
|
+
return this._ssrRenderTarget;
|
|
1383
|
+
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
/**
|
|
1387
|
+
* Frees internal resources. This method should be called
|
|
1388
|
+
* when the effect is no longer required.
|
|
1389
|
+
*/
|
|
1390
|
+
dispose() {
|
|
1391
|
+
|
|
1392
|
+
super.dispose();
|
|
1393
|
+
|
|
1394
|
+
this._ssrRenderTarget.dispose();
|
|
1395
|
+
this._blurRenderTarget.dispose();
|
|
1396
|
+
|
|
1397
|
+
this._ssrMaterial.dispose();
|
|
1398
|
+
this._blurMaterial.dispose();
|
|
1399
|
+
this._copyMaterial.dispose();
|
|
1400
|
+
|
|
1401
|
+
if ( this._importanceEnvironment !== null ) {
|
|
1402
|
+
|
|
1403
|
+
this._importanceEnvironment.dispose();
|
|
1404
|
+
this._importanceEnvironment = null;
|
|
1405
|
+
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
export default SSRNode;
|
|
1413
|
+
|
|
1414
|
+
/**
|
|
1415
|
+
* TSL function for creating screen space reflections (SSR).
|
|
1416
|
+
*
|
|
1417
|
+
* @tsl
|
|
1418
|
+
* @function
|
|
1419
|
+
* @param {Node<vec4>} colorNode - The node that represents the beauty pass.
|
|
1420
|
+
* @param {Node<float>} depthNode - A node that represents the beauty pass's depth.
|
|
1421
|
+
* @param {Node<vec3>} normalNode - A node that represents the beauty pass's normals.
|
|
1422
|
+
* @param {SSRNodeOptions} [options] - Optional inputs for material and environment data.
|
|
1423
|
+
* @returns {SSRNode}
|
|
1424
|
+
*/
|
|
1425
|
+
export const ssr = ( colorNode, depthNode, normalNode, options = {} ) => new SSRNode(
|
|
1426
|
+
nodeObject( colorNode ),
|
|
1427
|
+
nodeObject( depthNode ),
|
|
1428
|
+
nodeObject( normalNode ),
|
|
1429
|
+
options
|
|
1430
|
+
);
|