@unikia/upe-renderer 0.186.110 → 0.187.11

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.
Files changed (506) hide show
  1. package/README.md +5 -7
  2. package/UPSTREAM.md +4 -4
  3. package/build/three.core.js +853 -277
  4. package/build/three.module.js +1098 -1280
  5. package/build/three.tsl.js +41938 -686
  6. package/build/three.webgpu.js +10604 -49055
  7. package/build/three.webgpu.nodes.js +9249 -5788
  8. package/examples/jsm/Addons.js +2 -0
  9. package/examples/jsm/animation/CCDIKSolver.js +17 -5
  10. package/examples/jsm/controls/FirstPersonControls.js +1 -1
  11. package/examples/jsm/controls/OrbitControls.js +27 -14
  12. package/examples/jsm/csm/CSMShader.js +74 -3
  13. package/examples/jsm/curves/CurveExtras.js +4 -4
  14. package/examples/jsm/curves/NURBSCurve.js +14 -0
  15. package/examples/jsm/exporters/EXRExporter.js +673 -16
  16. package/examples/jsm/exporters/GLTFExporter.js +4 -4
  17. package/examples/jsm/exporters/KTX2Exporter.js +1 -1
  18. package/examples/jsm/exporters/OBJExporter.js +48 -5
  19. package/examples/jsm/exporters/PLYExporter.js +22 -11
  20. package/examples/jsm/generators/CityGenerator.js +3 -2
  21. package/examples/jsm/generators/city/SkyscraperGenerator.js +63 -21
  22. package/examples/jsm/gpgpu/BitonicSort.js +30 -23
  23. package/examples/jsm/helpers/VertexTangentsHelper.js +1 -1
  24. package/examples/jsm/inspector/Extension.js +1 -1
  25. package/examples/jsm/inspector/Inspector.js +6 -46
  26. package/examples/jsm/inspector/RendererInspector.js +43 -8
  27. package/examples/jsm/inspector/Storage.js +49 -0
  28. package/examples/jsm/inspector/extensions/color-grading/ColorGrading.js +32 -27
  29. package/examples/jsm/inspector/tabs/Parameters.js +5 -1
  30. package/examples/jsm/inspector/tabs/Performance.js +22 -7
  31. package/examples/jsm/inspector/tabs/Settings.js +1 -1
  32. package/examples/jsm/inspector/tabs/Timeline.js +83 -7
  33. package/examples/jsm/inspector/tabs/Viewer.js +25 -10
  34. package/examples/jsm/inspector/ui/Profiler.js +1 -1
  35. package/examples/jsm/inspector/ui/Style.js +21 -53
  36. package/examples/jsm/inspector/ui/Values.js +28 -3
  37. package/examples/jsm/libs/fflate.module.js +83 -56
  38. package/examples/jsm/libs/mikktspace.README.md +27 -0
  39. package/examples/jsm/libs/mikktspace.module.js +721 -109
  40. package/examples/jsm/lighting/ClusteredLighting.js +100 -2
  41. package/examples/jsm/lighting/LightMapper.js +295 -0
  42. package/examples/jsm/lighting/LightProbeGrid.js +242 -139
  43. package/examples/jsm/lighting/LightProbeGridWebGL.js +30 -14
  44. package/examples/jsm/lighting/vxgi/VXGIConeTracer.js +54 -5
  45. package/examples/jsm/lighting/vxgi/VXGIIrradiance.js +43 -0
  46. package/examples/jsm/lighting/vxgi/VXGINode.js +13 -56
  47. package/examples/jsm/lighting/vxgi/VXGISceneCollector.js +316 -1
  48. package/examples/jsm/lighting/vxgi/VXGIVolume.js +69 -59
  49. package/examples/jsm/lights/SunLight.js +9 -4
  50. package/examples/jsm/lights/SunLightNode.js +3 -3
  51. package/examples/jsm/lines/LineMaterial.js +26 -10
  52. package/examples/jsm/loaders/3DMLoader.js +10 -1
  53. package/examples/jsm/loaders/3MFLoader.js +5 -1
  54. package/examples/jsm/loaders/AMFLoader.js +2 -0
  55. package/examples/jsm/loaders/BVHLoader.js +2 -0
  56. package/examples/jsm/loaders/ColladaLoader.js +8 -0
  57. package/examples/jsm/loaders/DDSLoader.js +1 -1
  58. package/examples/jsm/loaders/DRACOLoader.js +5 -1
  59. package/examples/jsm/loaders/EXRLoader.js +120 -104
  60. package/examples/jsm/loaders/FBXLoader.js +4 -0
  61. package/examples/jsm/loaders/FontLoader.js +2 -0
  62. package/examples/jsm/loaders/GCodeLoader.js +5 -9
  63. package/examples/jsm/loaders/GLTFLoader.js +112 -31
  64. package/examples/jsm/loaders/GaussianSplatPLYLoader.js +2 -0
  65. package/examples/jsm/loaders/HDRCubeTextureLoader.js +3 -0
  66. package/examples/jsm/loaders/IESLoader.js +46 -12
  67. package/examples/jsm/loaders/JXLLoader.js +159 -0
  68. package/examples/jsm/loaders/KMZLoader.js +6 -0
  69. package/examples/jsm/loaders/KSPLATLoader.js +2 -0
  70. package/examples/jsm/loaders/KTX2Loader.js +49 -4
  71. package/examples/jsm/loaders/KTXLoader.js +5 -3
  72. package/examples/jsm/loaders/LDrawLoader.js +15 -22
  73. package/examples/jsm/loaders/LUT3dlLoader.js +5 -1
  74. package/examples/jsm/loaders/LUTCubeLoader.js +6 -2
  75. package/examples/jsm/loaders/LUTImageLoader.js +2 -0
  76. package/examples/jsm/loaders/LWOLoader.js +6 -0
  77. package/examples/jsm/loaders/MD2Loader.js +2 -0
  78. package/examples/jsm/loaders/MDDLoader.js +4 -0
  79. package/examples/jsm/loaders/MTLLoader.js +8 -0
  80. package/examples/jsm/loaders/MaterialXLoader.js +57 -5
  81. package/examples/jsm/loaders/NRRDLoader.js +4 -2
  82. package/examples/jsm/loaders/OBJLoader.js +10 -4
  83. package/examples/jsm/loaders/PCDLoader.js +6 -2
  84. package/examples/jsm/loaders/PDBLoader.js +5 -3
  85. package/examples/jsm/loaders/PLYLoader.js +39 -15
  86. package/examples/jsm/loaders/PVRLoader.js +2 -2
  87. package/examples/jsm/loaders/SPLATLoader.js +2 -0
  88. package/examples/jsm/loaders/SPZLoader.js +2 -0
  89. package/examples/jsm/loaders/STLLoader.js +3 -1
  90. package/examples/jsm/loaders/SVGLoader.js +27 -49
  91. package/examples/jsm/loaders/TDSLoader.js +4 -0
  92. package/examples/jsm/loaders/TGALoader.js +6 -5
  93. package/examples/jsm/loaders/TTFLoader.js +2 -0
  94. package/examples/jsm/loaders/USDLoader.js +14 -0
  95. package/examples/jsm/loaders/UltraHDRLoader.js +2 -0
  96. package/examples/jsm/loaders/VOXLoader.js +3 -0
  97. package/examples/jsm/loaders/VRMLLoader.js +4 -0
  98. package/examples/jsm/loaders/VTKLoader.js +2 -0
  99. package/examples/jsm/loaders/XYZLoader.js +2 -0
  100. package/examples/jsm/loaders/collada/ColladaComposer.js +15 -8
  101. package/examples/jsm/loaders/materialx/MaterialXDocument.js +610 -138
  102. package/examples/jsm/loaders/materialx/MaterialXInterfaceValidation.js +12 -95
  103. package/examples/jsm/loaders/materialx/MaterialXLog.js +4 -0
  104. package/examples/jsm/loaders/materialx/MaterialXNodeDefs.js +99 -0
  105. package/examples/jsm/loaders/materialx/MaterialXNodeInterfaceRegistry.js +760 -1
  106. package/examples/jsm/loaders/materialx/MaterialXNodeLibrary.js +222 -372
  107. package/examples/jsm/loaders/materialx/MaterialXSurfaceMappings.js +163 -259
  108. package/examples/jsm/loaders/materialx/MaterialXUtils.js +25 -0
  109. package/examples/jsm/loaders/materialx/compile/MaterialXCompileRegistry.js +161 -159
  110. package/examples/jsm/loaders/usd/USDAParser.js +56 -47
  111. package/examples/jsm/loaders/usd/USDComposer.js +25 -30
  112. package/examples/jsm/math/ColorConverter.js +7 -3
  113. package/examples/jsm/math/Lut.js +2 -2
  114. package/examples/jsm/math/OBB.js +3 -3
  115. package/examples/jsm/math/Octree.js +20 -17
  116. package/examples/jsm/objects/GaussianSplat.js +5 -4
  117. package/examples/jsm/objects/Reflector.js +5 -0
  118. package/examples/jsm/objects/SkyMesh.js +14 -7
  119. package/examples/jsm/objects/Water2Mesh.js +2 -2
  120. package/examples/jsm/physics/RapierPhysics.js +2 -2
  121. package/examples/jsm/pipelines/MeshletDrawingPipeline.js +5571 -0
  122. package/examples/jsm/pipelines/VisibilityBufferDrawingPipeline.js +954 -0
  123. package/examples/jsm/postprocessing/BokehPass.js +1 -1
  124. package/examples/jsm/postprocessing/GTAOPass.js +26 -18
  125. package/examples/jsm/renderers/SVGRenderer.js +3 -2
  126. package/examples/jsm/shaders/GTAOShader.js +7 -4
  127. package/examples/jsm/shaders/PoissonDenoiseShader.js +1 -10
  128. package/examples/jsm/tsl/WebGLNodesHandler.js +21 -9
  129. package/examples/jsm/tsl/display/AfterImageNode.js +3 -3
  130. package/examples/jsm/tsl/display/BilateralBlurNode.js +3 -3
  131. package/examples/jsm/tsl/display/BloomNode.js +3 -3
  132. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +8 -19
  133. package/examples/jsm/tsl/display/DenoiseNode.js +5 -5
  134. package/examples/jsm/tsl/display/DepthOfFieldNode.js +3 -3
  135. package/examples/jsm/tsl/display/DotScreenNode.js +3 -3
  136. package/examples/jsm/tsl/display/FSR1Node.js +3 -3
  137. package/examples/jsm/tsl/display/FXAANode.js +3 -10
  138. package/examples/jsm/tsl/display/FilmNode.js +3 -3
  139. package/examples/jsm/tsl/display/GTAONode.js +33 -25
  140. package/examples/jsm/tsl/display/GaussianBlurNode.js +3 -3
  141. package/examples/jsm/tsl/display/GodraysNode.js +5 -19
  142. package/examples/jsm/tsl/display/ImportanceSampledEnvironment.js +8 -4
  143. package/examples/jsm/tsl/display/LensflareNode.js +3 -3
  144. package/examples/jsm/tsl/display/Lut3DNode.js +3 -3
  145. package/examples/jsm/tsl/display/OITPassNode.js +0 -11
  146. package/examples/jsm/tsl/display/OutlineNode.js +107 -5
  147. package/examples/jsm/tsl/display/PixelationPassNode.js +85 -193
  148. package/examples/jsm/tsl/display/RGBShiftNode.js +3 -3
  149. package/examples/jsm/tsl/display/RecurrentDenoiseNode.js +23 -126
  150. package/examples/jsm/tsl/display/SMAANode.js +3 -3
  151. package/examples/jsm/tsl/display/SSAONode.js +6 -20
  152. package/examples/jsm/tsl/display/SSGINode.js +36 -29
  153. package/examples/jsm/tsl/display/SSRNode.js +135 -63
  154. package/examples/jsm/tsl/display/SSSNode.js +6 -20
  155. package/examples/jsm/tsl/display/SharpenNode.js +3 -3
  156. package/examples/jsm/tsl/display/SobelOperatorNode.js +3 -3
  157. package/examples/jsm/tsl/display/TAAUNode.js +10 -42
  158. package/examples/jsm/tsl/display/TRAANode.js +11 -43
  159. package/examples/jsm/tsl/display/TemporalReprojectNode.js +42 -47
  160. package/examples/jsm/tsl/display/TransitionNode.js +3 -3
  161. package/examples/jsm/tsl/display/lensDirt.js +30 -0
  162. package/examples/jsm/tsl/lighting/ClusteredLightsNode.js +482 -121
  163. package/examples/jsm/tsl/lighting/DynamicLightsNode.js +41 -140
  164. package/examples/jsm/tsl/lighting/LightProbeGridNode.js +72 -25
  165. package/examples/jsm/tsl/lighting/data/AmbientLightDataNode.js +6 -0
  166. package/examples/jsm/tsl/lighting/data/DirectionalLightDataNode.js +6 -0
  167. package/examples/jsm/tsl/lighting/data/HemisphereLightDataNode.js +6 -0
  168. package/examples/jsm/tsl/lighting/data/PointLightDataNode.js +6 -0
  169. package/examples/jsm/tsl/lighting/data/SpotLightDataNode.js +6 -0
  170. package/examples/jsm/tsl/shadows/TileShadowNode.js +102 -14
  171. package/examples/jsm/tsl/utils/Raymarching.js +1 -1
  172. package/examples/jsm/tsl/utils/SoftParticles.js +5 -12
  173. package/examples/jsm/tsl/utils/SpecularHelpers.js +47 -70
  174. package/examples/jsm/tsl/utils/TAAUtils.js +6 -17
  175. package/examples/jsm/utils/BufferGeometryUtils.js +110 -88
  176. package/examples/jsm/utils/MeshletGeometryUtils.js +417 -0
  177. package/examples/jsm/utils/SceneOptimizer.js +2 -1
  178. package/examples/jsm/utils/SceneUtils.js +1 -1
  179. package/examples/jsm/utils/unwrapUVs.js +865 -0
  180. package/examples/jsm/webxr/XREstimatedLight.js +11 -4
  181. package/package.json +3 -3
  182. package/src/Three.TSL.js +2 -683
  183. package/src/Three.WebGPU.Nodes.js +2 -1
  184. package/src/Three.WebGPU.js +2 -1
  185. package/src/animation/AnimationAction.js +1 -1
  186. package/src/animation/AnimationUtils.js +1 -3
  187. package/src/animation/KeyframeTrack.js +19 -0
  188. package/src/cameras/ArrayCamera.js +12 -0
  189. package/src/cameras/CubeCamera.js +3 -3
  190. package/src/constants.js +1 -9
  191. package/src/core/BufferAttribute.js +57 -21
  192. package/src/core/BufferGeometry.js +5 -13
  193. package/src/core/Clock.js +1 -1
  194. package/src/core/InterleavedBuffer.js +28 -18
  195. package/src/core/InterleavedBufferAttribute.js +54 -20
  196. package/src/core/Object3D.js +19 -9
  197. package/src/core/Raycaster.js +2 -0
  198. package/src/core/RenderTarget.js +11 -5
  199. package/src/core/UniformsGroup.js +7 -3
  200. package/src/extras/PMREMGenerator.js +392 -685
  201. package/src/extras/core/Curve.js +4 -0
  202. package/src/extras/core/CurvePath.js +13 -0
  203. package/src/extras/core/ShapePath.js +1 -1
  204. package/src/geometries/EdgesGeometry.js +12 -10
  205. package/src/geometries/LatheGeometry.js +2 -0
  206. package/src/helpers/PolarGridHelper.js +1 -1
  207. package/src/lights/Light.js +11 -0
  208. package/src/lights/LightProbe.js +2 -0
  209. package/src/lights/LightShadow.js +2 -0
  210. package/src/loaders/AnimationLoader.js +2 -0
  211. package/src/loaders/AudioLoader.js +2 -0
  212. package/src/loaders/BufferGeometryLoader.js +2 -0
  213. package/src/loaders/CompressedTextureLoader.js +2 -0
  214. package/src/loaders/CubeTextureLoader.js +2 -0
  215. package/src/loaders/DataTextureLoader.js +2 -0
  216. package/src/loaders/FileLoader.js +2 -0
  217. package/src/loaders/ImageBitmapLoader.js +3 -1
  218. package/src/loaders/ImageLoader.js +1 -0
  219. package/src/loaders/Loader.js +47 -0
  220. package/src/loaders/MaterialLoader.js +2 -0
  221. package/src/loaders/ObjectLoader.js +27 -8
  222. package/src/loaders/TextureLoader.js +5 -3
  223. package/src/loaders/nodes/NodeLoader.js +2 -0
  224. package/src/materials/Material.js +21 -2
  225. package/src/materials/MeshDepthMaterial.js +1 -1
  226. package/src/materials/MeshDistanceMaterial.js +1 -1
  227. package/src/materials/MeshLambertMaterial.js +1 -1
  228. package/src/materials/MeshMatcapMaterial.js +1 -1
  229. package/src/materials/MeshNormalMaterial.js +1 -1
  230. package/src/materials/MeshPhongMaterial.js +1 -1
  231. package/src/materials/MeshPhysicalMaterial.js +90 -11
  232. package/src/materials/MeshStandardMaterial.js +1 -1
  233. package/src/materials/MeshToonMaterial.js +1 -1
  234. package/src/materials/nodes/Line2NodeMaterial.js +32 -10
  235. package/src/materials/nodes/MeshLambertNodeMaterial.js +13 -0
  236. package/src/materials/nodes/MeshPhongNodeMaterial.js +13 -0
  237. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +40 -5
  238. package/src/materials/nodes/MeshToonNodeMaterial.js +13 -0
  239. package/src/materials/nodes/NodeMaterial.js +36 -16
  240. package/src/materials/nodes/NodeMaterialInstance.js +193 -0
  241. package/src/materials/nodes/NodeMaterials.js +1 -0
  242. package/src/materials/nodes/PointsNodeMaterial.js +1 -1
  243. package/src/materials/nodes/SpriteNodeMaterial.js +3 -3
  244. package/src/materials/nodes/manager/NodeMaterialObserver.js +191 -22
  245. package/src/math/Box3.js +2 -2
  246. package/src/math/Color.js +8 -8
  247. package/src/math/ColorManagement.js +2 -21
  248. package/src/math/FrustumArray.js +12 -0
  249. package/src/math/Interpolant.js +1 -1
  250. package/src/math/Line3.js +2 -4
  251. package/src/math/MathUtils.js +33 -46
  252. package/src/math/Matrix2.js +1 -1
  253. package/src/math/Matrix3.js +1 -1
  254. package/src/math/Matrix4.js +1 -1
  255. package/src/math/Triangle.js +2 -1
  256. package/src/math/Vector2.js +1 -1
  257. package/src/math/Vector3.js +1 -1
  258. package/src/math/Vector4.js +1 -1
  259. package/src/nodes/Nodes.js +1 -0
  260. package/src/nodes/TSL.js +2 -0
  261. package/src/nodes/accessors/Arrays.js +1 -1
  262. package/src/nodes/accessors/Batch.js +29 -23
  263. package/src/nodes/accessors/BufferAttributeNode.js +21 -1
  264. package/src/nodes/accessors/BuiltinNode.js +6 -0
  265. package/src/nodes/accessors/Camera.js +100 -93
  266. package/src/nodes/accessors/ClippingNode.js +17 -6
  267. package/src/nodes/accessors/CubeTextureNode.js +12 -24
  268. package/src/nodes/accessors/Instance.js +198 -160
  269. package/src/nodes/accessors/Lights.js +19 -6
  270. package/src/nodes/accessors/MaterialNode.js +33 -4
  271. package/src/nodes/accessors/Morph.js +81 -22
  272. package/src/nodes/accessors/Normal.js +0 -42
  273. package/src/nodes/accessors/Object3DNode.js +6 -0
  274. package/src/nodes/accessors/PointUVNode.js +6 -0
  275. package/src/nodes/accessors/ReferenceAttributeNode.js +279 -0
  276. package/src/nodes/accessors/ReferenceBaseNode.js +6 -0
  277. package/src/nodes/accessors/ReferenceNode.js +6 -0
  278. package/src/nodes/accessors/Skinning.js +57 -52
  279. package/src/nodes/accessors/StorageBufferNode.js +3 -12
  280. package/src/nodes/accessors/TextureBicubic.js +30 -27
  281. package/src/nodes/accessors/TextureNode.js +164 -78
  282. package/src/nodes/accessors/TextureSizeNode.js +6 -0
  283. package/src/nodes/accessors/UniformArrayNode.js +8 -15
  284. package/src/nodes/accessors/VelocityNode.js +13 -8
  285. package/src/nodes/code/CodeNode.js +6 -0
  286. package/src/nodes/code/ExpressionNode.js +6 -0
  287. package/src/nodes/code/FunctionCallNode.js +3 -3
  288. package/src/nodes/code/FunctionNode.js +15 -13
  289. package/src/nodes/core/ArrayNode.js +3 -3
  290. package/src/nodes/core/AssignNode.js +10 -9
  291. package/src/nodes/core/AttributeNode.js +39 -0
  292. package/src/nodes/core/BypassNode.js +6 -0
  293. package/src/nodes/core/ConstNode.js +31 -1
  294. package/src/nodes/core/ContextNode.js +11 -6
  295. package/src/nodes/core/IndexNode.js +6 -0
  296. package/src/nodes/core/InputNode.js +6 -0
  297. package/src/nodes/core/InspectorNode.js +17 -31
  298. package/src/nodes/core/IsolateNode.js +8 -0
  299. package/src/nodes/core/Node.js +367 -67
  300. package/src/nodes/core/NodeBuilder.js +664 -222
  301. package/src/nodes/core/NodeUtils.js +25 -0
  302. package/src/nodes/core/NodeVar.js +10 -1
  303. package/src/nodes/core/OutputStructNode.js +6 -0
  304. package/src/nodes/core/OverrideContextNode.js +38 -37
  305. package/src/nodes/core/PropertyNode.js +14 -0
  306. package/src/nodes/core/StackNode.js +33 -21
  307. package/src/nodes/core/StructNode.js +6 -0
  308. package/src/nodes/core/StructTypeNode.js +6 -0
  309. package/src/nodes/core/SubBuildNode.js +8 -0
  310. package/src/nodes/core/TempNode.js +10 -35
  311. package/src/nodes/core/UniformGroupNode.js +6 -0
  312. package/src/nodes/core/VarNode.js +43 -135
  313. package/src/nodes/core/VaryingNode.js +33 -2
  314. package/src/nodes/display/BlendModes.js +5 -40
  315. package/src/nodes/display/BumpMapNode.js +17 -7
  316. package/src/nodes/display/ColorAdjustment.js +22 -10
  317. package/src/nodes/display/ColorSpaceFunctions.js +2 -14
  318. package/src/nodes/display/ColorSpaceNode.js +3 -3
  319. package/src/nodes/display/FrontFacingNode.js +6 -0
  320. package/src/nodes/display/NormalMapNode.js +3 -3
  321. package/src/nodes/display/PassNode.js +75 -16
  322. package/src/nodes/display/RenderOutputNode.js +22 -5
  323. package/src/nodes/display/ScreenNode.js +6 -0
  324. package/src/nodes/display/ToneMappingFunctions.js +9 -51
  325. package/src/nodes/display/ToneMappingNode.js +3 -3
  326. package/src/nodes/display/ToonOutlinePassNode.js +66 -2
  327. package/src/nodes/display/ViewportDepthNode.js +34 -4
  328. package/src/nodes/functions/BSDF/BRDF_EON.js +65 -0
  329. package/src/nodes/functions/BSDF/BRDF_GGX.js +5 -3
  330. package/src/nodes/functions/BSDF/BRDF_Sheen.js +2 -16
  331. package/src/nodes/functions/BSDF/D_GGX.js +1 -8
  332. package/src/nodes/functions/BSDF/D_GGX_Anisotropic.js +7 -10
  333. package/src/nodes/functions/BSDF/LTC.js +20 -47
  334. package/src/nodes/functions/BSDF/Schlick_to_F0.js +1 -9
  335. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated.js +1 -9
  336. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +10 -13
  337. package/src/nodes/functions/PhysicalLightingModel.js +84 -51
  338. package/src/nodes/functions/VolumetricLightingModel.js +1 -1
  339. package/src/nodes/functions/material/getAlphaHashThreshold.js +3 -9
  340. package/src/nodes/functions/material/getParallaxCorrectNormal.js +10 -11
  341. package/src/nodes/functions/material/getRoughness.js +3 -1
  342. package/src/nodes/geometry/RangeNode.js +52 -69
  343. package/src/nodes/gpgpu/AtomicFunctionNode.js +11 -6
  344. package/src/nodes/gpgpu/BarrierNode.js +6 -0
  345. package/src/nodes/gpgpu/ComputeBuiltinNode.js +6 -0
  346. package/src/nodes/gpgpu/ComputeNode.js +6 -0
  347. package/src/nodes/gpgpu/SubgroupFunctionNode.js +38 -29
  348. package/src/nodes/gpgpu/WorkgroupInfoNode.js +6 -0
  349. package/src/nodes/lighting/AnalyticLightNode.js +7 -14
  350. package/src/nodes/lighting/BasicEnvironmentNode.js +5 -1
  351. package/src/nodes/lighting/EnvironmentNode.js +58 -8
  352. package/src/nodes/lighting/IESSpotLightNode.js +19 -4
  353. package/src/nodes/lighting/LightProbeNode.js +2 -1
  354. package/src/nodes/lighting/LightUtils.js +2 -2
  355. package/src/nodes/lighting/LightingNode.js +6 -0
  356. package/src/nodes/lighting/LightsNode.js +26 -32
  357. package/src/nodes/lighting/PointShadowNode.js +92 -48
  358. package/src/nodes/lighting/ProjectorLightNode.js +1 -1
  359. package/src/nodes/lighting/RectAreaLightNode.js +13 -14
  360. package/src/nodes/lighting/ShadowBaseNode.js +9 -17
  361. package/src/nodes/lighting/ShadowFilterNode.js +26 -3
  362. package/src/nodes/lighting/ShadowNode.js +13 -11
  363. package/src/nodes/materialx/MaterialXColor.js +2 -14
  364. package/src/nodes/materialx/MaterialXColorTransform.js +1 -7
  365. package/src/nodes/materialx/MaterialXNodes.js +8 -11
  366. package/src/nodes/materialx/MaterialXNoise.js +195 -454
  367. package/src/nodes/math/BitcastNode.js +5 -5
  368. package/src/nodes/math/BitcountNode.js +18 -46
  369. package/src/nodes/math/ConditionalNode.js +92 -22
  370. package/src/nodes/math/Hash.js +1 -1
  371. package/src/nodes/math/MathNode.js +86 -64
  372. package/src/nodes/math/MathUtils.js +2 -2
  373. package/src/nodes/math/OperatorNode.js +42 -59
  374. package/src/nodes/math/PackFloatNode.js +9 -9
  375. package/src/nodes/math/Packed4x8IntegerNode.js +20 -52
  376. package/src/nodes/math/TriNoise3D.js +3 -23
  377. package/src/nodes/math/UnpackFloatNode.js +9 -9
  378. package/src/nodes/pmrem/PMREMNode.js +38 -75
  379. package/src/nodes/pmrem/PMREMUtils.js +108 -272
  380. package/src/nodes/procedural/Checker.js +1 -1
  381. package/src/nodes/tsl/TSLCore.js +199 -74
  382. package/src/nodes/utils/ArrayElementNode.js +19 -1
  383. package/src/nodes/utils/CubeMapNode.js +3 -3
  384. package/src/nodes/utils/DebugNode.js +2 -2
  385. package/src/nodes/utils/EventNode.js +6 -0
  386. package/src/nodes/utils/FlipNode.js +3 -3
  387. package/src/nodes/utils/FunctionOverloadingNode.js +7 -1
  388. package/src/nodes/utils/JoinNode.js +3 -3
  389. package/src/nodes/utils/LoopNode.js +14 -9
  390. package/src/nodes/utils/MemberNode.js +18 -0
  391. package/src/nodes/utils/PostProcessingUtils.js +20 -25
  392. package/src/nodes/utils/RTTNode.js +2 -0
  393. package/src/nodes/utils/ReflectorNode.js +24 -0
  394. package/src/nodes/utils/RotateNode.js +3 -3
  395. package/src/nodes/utils/SampleNode.js +6 -0
  396. package/src/nodes/utils/SetNode.js +3 -3
  397. package/src/nodes/utils/SplitNode.js +6 -0
  398. package/src/nodes/utils/UVUtils.js +2 -2
  399. package/src/objects/BatchedMesh.js +146 -15
  400. package/src/objects/InstancedMesh.js +12 -4
  401. package/src/objects/Line.js +20 -0
  402. package/src/objects/Mesh.js +8 -0
  403. package/src/objects/Points.js +20 -0
  404. package/src/objects/Skeleton.js +26 -0
  405. package/src/objects/SkinnedMesh.js +3 -3
  406. package/src/objects/Sprite.js +10 -0
  407. package/src/renderers/WebGLRenderer.js +104 -70
  408. package/src/renderers/common/Animation.js +5 -1
  409. package/src/renderers/common/Attributes.js +67 -57
  410. package/src/renderers/common/Backend.js +78 -3
  411. package/src/renderers/common/BindGroup.js +11 -0
  412. package/src/renderers/common/Binding.js +0 -11
  413. package/src/renderers/common/Bindings.js +116 -10
  414. package/src/renderers/common/Buffer.js +1 -1
  415. package/src/renderers/common/ClippingContext.js +12 -1
  416. package/src/renderers/common/ComputePipeline.js +17 -1
  417. package/src/renderers/common/DirectRenderPipeline.js +7 -3
  418. package/src/renderers/common/Geometries.js +170 -132
  419. package/src/renderers/common/Info.js +1 -1
  420. package/src/renderers/common/InspectorBase.js +5 -5
  421. package/src/renderers/common/Lighting.js +59 -0
  422. package/src/renderers/common/Pipelines.js +26 -12
  423. package/src/renderers/common/ProgrammableStage.js +1 -17
  424. package/src/renderers/common/RenderContext.js +21 -0
  425. package/src/renderers/common/RenderContexts.js +13 -4
  426. package/src/renderers/common/RenderObject.js +111 -35
  427. package/src/renderers/common/RenderObjects.js +37 -19
  428. package/src/renderers/common/Renderer.js +537 -295
  429. package/src/renderers/common/RendererUtils.js +15 -0
  430. package/src/renderers/common/StandardDrawingPipeline.js +343 -0
  431. package/src/renderers/common/Storage3DTexture.js +11 -0
  432. package/src/renderers/common/StorageArrayTexture.js +10 -0
  433. package/src/renderers/common/StorageTexture.js +0 -9
  434. package/src/renderers/common/Textures.js +144 -37
  435. package/src/renderers/common/UniformsGroup.js +19 -0
  436. package/src/renderers/common/XRManager.js +10 -91
  437. package/src/renderers/common/extras/PMREMGenerator.js +298 -576
  438. package/src/renderers/common/nodes/NodeBuilderState.js +7 -5
  439. package/src/renderers/common/nodes/NodeLibrary.js +11 -35
  440. package/src/renderers/common/nodes/NodeManager.js +80 -31
  441. package/src/renderers/common/nodes/NodeSampledTexture.js +14 -0
  442. package/src/renderers/common/nodes/NodeSampler.js +14 -0
  443. package/src/renderers/common/nodes/NodeStorageBuffer.js +1 -1
  444. package/src/renderers/common/nodes/NodeUniformBuffer.js +1 -14
  445. package/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js +13 -4
  446. package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +8 -8
  447. package/src/renderers/shaders/ShaderChunk/lightprobes_pars_fragment.glsl.js +23 -11
  448. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +21 -2
  449. package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +1 -1
  450. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +18 -2
  451. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +104 -7
  452. package/src/renderers/shaders/ShaderChunk/morphcolor_vertex.glsl.js +11 -2
  453. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +36 -20
  454. package/src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl.js +5 -0
  455. package/src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl.js +6 -0
  456. package/src/renderers/shaders/ShaderChunk/uv_vertex.glsl.js +5 -0
  457. package/src/renderers/shaders/ShaderChunk.js +0 -2
  458. package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +4 -18
  459. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +0 -1
  460. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +0 -1
  461. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +8 -1
  462. package/src/renderers/shaders/ShaderLib.js +3 -0
  463. package/src/renderers/shaders/UniformsLib.js +4 -5
  464. package/src/renderers/webgl/WebGLBackground.js +3 -3
  465. package/src/renderers/webgl/WebGLBindingStates.js +4 -2
  466. package/src/renderers/webgl/WebGLCapabilities.js +7 -1
  467. package/src/renderers/webgl/WebGLEnvironments.js +2 -2
  468. package/src/renderers/webgl/WebGLGeometries.js +42 -14
  469. package/src/renderers/webgl/WebGLMaterials.js +15 -2
  470. package/src/renderers/webgl/WebGLOutput.js +37 -1
  471. package/src/renderers/webgl/WebGLProgram.js +13 -54
  472. package/src/renderers/webgl/WebGLPrograms.js +22 -8
  473. package/src/renderers/webgl/WebGLRenderStates.js +11 -8
  474. package/src/renderers/webgl/WebGLShadowMap.js +6 -4
  475. package/src/renderers/webgl/WebGLState.js +10 -6
  476. package/src/renderers/webgl/WebGLTextures.js +129 -77
  477. package/src/renderers/webgl/WebGLUniforms.js +44 -6
  478. package/src/renderers/webgl/WebGLUniformsGroups.js +75 -69
  479. package/src/renderers/webgl-fallback/WebGLBackend.js +206 -278
  480. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +154 -20
  481. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +45 -42
  482. package/src/renderers/webgl-fallback/utils/WebGLState.js +29 -4
  483. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +129 -49
  484. package/src/renderers/webgl-fallback/utils/WebGLVertexArrayUtils.js +346 -0
  485. package/src/renderers/webgpu/WebGPUBackend.js +140 -82
  486. package/src/renderers/webgpu/WebGPURenderer.js +1 -1
  487. package/src/renderers/webgpu/nodes/BasicNodeLibrary.js +10 -10
  488. package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +10 -10
  489. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +135 -60
  490. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +128 -55
  491. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +1 -1
  492. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +15 -12
  493. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +55 -19
  494. package/src/renderers/webgpu/utils/WebGPUUtils.js +20 -3
  495. package/src/renderers/webxr/WebXRController.js +3 -3
  496. package/src/renderers/webxr/WebXRManager.js +5 -90
  497. package/src/scenes/Scene.js +4 -4
  498. package/src/textures/CompressedTexture.js +2 -2
  499. package/src/textures/DepthTexture.js +2 -2
  500. package/src/textures/FramebufferTexture.js +11 -0
  501. package/src/textures/Texture.js +29 -1
  502. package/src/textures/TextureSource.js +1 -1
  503. package/src/upe.js +1 -1
  504. package/src/utils.js +4 -4
  505. package/examples/jsm/libs/surfaceNet.js +0 -201
  506. package/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js +0 -186
@@ -3,8 +3,8 @@
3
3
  * Copyright 2010-2026 Three.js Authors
4
4
  * SPDX-License-Identifier: MIT
5
5
  */
6
- import { Matrix3, Vector2, Color, Vector3, mergeUniforms, CubeUVReflectionMapping, Mesh, BoxGeometry, ShaderMaterial, BackSide, cloneUniforms, Matrix4, ColorManagement, SRGBTransfer, PlaneGeometry, FrontSide, getUnlitUniformColorSpace, IntType, warn, HalfFloatType, UnsignedByteType, FloatType, RGBAFormat, Plane, CubeReflectionMapping, CubeRefractionMapping, BufferGeometry, OrthographicCamera, PerspectiveCamera, NoToneMapping, MeshBasicMaterial, NoBlending, WebGLRenderTarget, BufferAttribute, LinearSRGBColorSpace, LinearFilter, CubeTexture, LinearMipmapLinearFilter, CubeCamera, EquirectangularReflectionMapping, EquirectangularRefractionMapping, warnOnce, Uint32BufferAttribute, Uint16BufferAttribute, error, DataArrayTexture, Vector4, Float32BufferAttribute, RawShaderMaterial, CustomToneMapping, NeutralToneMapping, AgXToneMapping, ACESFilmicToneMapping, CineonToneMapping, ReinhardToneMapping, LinearToneMapping, Data3DTexture, GreaterEqualCompare, LessEqualCompare, DepthTexture, Texture, GLSL3, VSMShadowMap, PCFShadowMap, AddOperation, MixOperation, MultiplyOperation, LinearTransfer, UniformsUtils, DoubleSide, NormalBlending, TangentSpaceNormalMap, ObjectSpaceNormalMap, Layers, RGFormat, RG11_EAC_Format, RED_GREEN_RGTC2_Format, MeshDepthMaterial, MeshDistanceMaterial, PCFSoftShadowMap, DepthFormat, NearestFilter, CubeDepthTexture, UnsignedIntType, Frustum, LessEqualDepth, ReverseSubtractEquation, SubtractEquation, AddEquation, OneMinusConstantAlphaFactor, ConstantAlphaFactor, OneMinusConstantColorFactor, ConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, DstAlphaFactor, DstColorFactor, SrcAlphaSaturateFactor, SrcAlphaFactor, SrcColorFactor, OneFactor, ZeroFactor, NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessDepth, AlwaysDepth, NeverDepth, CullFaceNone, CullFaceBack, CullFaceFront, CustomBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, ReversedDepthFuncs, MinEquation, MaxEquation, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, LinearMipmapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NotEqualCompare, GreaterCompare, EqualCompare, LessCompare, AlwaysCompare, NeverCompare, NoColorSpace, DepthStencilFormat, getByteLength, UnsignedInt248Type, UnsignedShortType, createElementNS, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedInt5999Type, UnsignedInt101111Type, ByteType, ShortType, AlphaFormat, RGBFormat, RedFormat, RedIntegerFormat, RGIntegerFormat, RGBAIntegerFormat, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, R11_EAC_Format, SIGNED_R11_EAC_Format, SIGNED_RG11_EAC_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_BPTC_Format, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, SIGNED_RED_GREEN_RGTC2_Format, ExternalTexture, EventDispatcher, ArrayCamera, WebXRController, RAD2DEG, DataTexture, createCanvasElement, SRGBColorSpace, REVISION, log, WebGLCoordinateSystem, probeAsync } from './three.core.js';
7
- export { AdditiveAnimationBlendMode, AlwaysStencilFunc, AmbientLight, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BasicDepthPacking, BasicShadowMap, BatchedMesh, BezierInterpolant, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxHelper, BufferGeometryLoader, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CircleGeometry, Clock, ColorKeyframeTrack, Compatibility, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, Controls, CubeTextureLoader, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceFrontBack, Curve, CurvePath, CylinderGeometry, Cylindrical, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualStencilFunc, Euler, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Fog, FogExp2, FramebufferTexture, FrustumArray, GLBufferAttribute, GLSL1, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HTMLTexture, HemisphereLight, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateBezier, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InterpolationSamplingMode, InterpolationSamplingType, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, LightShadow, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, MOUSE, Material, MaterialBlending, MaterialLoader, MathUtils, Matrix2, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NeverStencilFunc, NoNormalPacking, NormalAnimationBlendMode, NormalGAPacking, NormalRGPacking, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, OctahedronGeometry, Path, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RGBADepthPacking, RGBDepthPacking, RGBIntegerFormat, RGDepthPacking, Ray, Raycaster, RectAreaLight, RenderObjectRefreshType, RenderTarget, RenderTarget3D, ReplaceStencilOp, RingGeometry, Scene, ShadowMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, TOUCH, TetrahedronGeometry, TextureLoader, TextureSource, TextureUtils, Timer, TimestampQuery, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, UPE_RENDERER, UPE_REVISION, UVMapping, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, VectorKeyframeTrack, VideoFrameTexture, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGPUCoordinateSystem, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, ZeroStencilOp, getConsoleFunction, setConsoleFunction } from './three.core.js';
6
+ import { Matrix3, Vector2, Color, mergeUniforms, Vector3, Mesh, BoxGeometry, ShaderMaterial, BackSide, cloneUniforms, Matrix4, ColorManagement, SRGBTransfer, PlaneGeometry, FrontSide, getUnlitUniformColorSpace, IntType, warn, HalfFloatType, UnsignedByteType, FloatType, RGBAFormat, Plane, WebGLRenderTarget, CubeTexture, NoBlending, LinearMipmapLinearFilter, LinearFilter, CubeCamera, floorPowerOfTwo, CubeReflectionMapping, CubeRefractionMapping, LinearSRGBColorSpace, EquirectangularReflectionMapping, EquirectangularRefractionMapping, warnOnce, Uint32BufferAttribute, Uint16BufferAttribute, error, DataArrayTexture, Vector4, BufferGeometry, Float32BufferAttribute, RawShaderMaterial, OrthographicCamera, DepthTexture, DepthStencilFormat, UnsignedInt248Type, NoToneMapping, CustomToneMapping, NeutralToneMapping, AgXToneMapping, ACESFilmicToneMapping, CineonToneMapping, ReinhardToneMapping, LinearToneMapping, Data3DTexture, AlwaysCompare, Texture, CubeDepthTexture, GLSL3, VSMShadowMap, PCFShadowMap, AddOperation, MixOperation, MultiplyOperation, LinearTransfer, UniformsUtils, DoubleSide, NormalBlending, TangentSpaceNormalMap, ObjectSpaceNormalMap, Layers, RGFormat, RG11_EAC_Format, RED_GREEN_RGTC2_Format, MeshDepthMaterial, MeshDistanceMaterial, BufferAttribute, PCFSoftShadowMap, DepthFormat, NearestFilter, UnsignedIntType, GreaterEqualCompare, LessEqualCompare, Frustum, LessEqualDepth, ReverseSubtractEquation, SubtractEquation, AddEquation, OneMinusConstantAlphaFactor, ConstantAlphaFactor, OneMinusConstantColorFactor, ConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, DstAlphaFactor, DstColorFactor, SrcAlphaSaturateFactor, SrcAlphaFactor, SrcColorFactor, OneFactor, ZeroFactor, NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessDepth, AlwaysDepth, NeverDepth, CullFaceNone, CullFaceBack, CullFaceFront, CustomBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, ReversedDepthFuncs, MinEquation, MaxEquation, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, LinearMipmapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NotEqualCompare, GreaterCompare, EqualCompare, LessCompare, NeverCompare, NoColorSpace, getByteLength, UnsignedShortType, createElementNS, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedInt5999Type, UnsignedInt101111Type, ByteType, ShortType, AlphaFormat, RGBFormat, RedFormat, RedIntegerFormat, RGIntegerFormat, RGBAIntegerFormat, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, R11_EAC_Format, SIGNED_R11_EAC_Format, SIGNED_RG11_EAC_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_BPTC_Format, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, SIGNED_RED_GREEN_RGTC2_Format, ExternalTexture, EventDispatcher, PerspectiveCamera, ArrayCamera, WebXRController, RAD2DEG, DataTexture, createCanvasElement, SRGBColorSpace, REVISION, log, FrustumArray, WebGLCoordinateSystem, probeAsync } from './three.core.js';
7
+ export { AdditiveAnimationBlendMode, AlwaysStencilFunc, AmbientLight, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BasicDepthPacking, BasicShadowMap, BatchedMesh, BezierInterpolant, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxHelper, BufferGeometryLoader, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CircleGeometry, Clock, ColorKeyframeTrack, Compatibility, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, Controls, CubeTextureLoader, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceFrontBack, Curve, CurvePath, CylinderGeometry, Cylindrical, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualStencilFunc, Euler, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Fog, FogExp2, FramebufferTexture, GLBufferAttribute, GLSL1, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HTMLTexture, HemisphereLight, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateBezier, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InterpolationSamplingMode, InterpolationSamplingType, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, LightShadow, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, MOUSE, Material, MaterialBlending, MaterialLoader, MathUtils, Matrix2, MeshBasicMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NeverStencilFunc, NoNormalPacking, NormalAnimationBlendMode, NormalGAPacking, NormalRGPacking, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, OctahedronGeometry, Path, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RGBADepthPacking, RGBDepthPacking, RGBIntegerFormat, RGDepthPacking, Ray, Raycaster, RectAreaLight, RenderObjectRefreshType, RenderTarget, RenderTarget3D, ReplaceStencilOp, RingGeometry, Scene, ShadowMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, TOUCH, TetrahedronGeometry, TextureLoader, TextureSource, TextureUtils, Timer, TimestampQuery, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, UPE_RENDERER, UPE_REVISION, UVMapping, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, VectorKeyframeTrack, VideoFrameTexture, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGPUCoordinateSystem, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, ZeroStencilOp, getConsoleFunction, setConsoleFunction } from './three.core.js';
8
8
 
9
9
  function WebGLAnimation() {
10
10
 
@@ -342,8 +342,6 @@ var color_vertex = "#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA ) || de
342
342
 
343
343
  var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\n#define inverseTransformDirection transformDirectionByInverseViewMatrix\nvec3 transformNormalByInverseViewMatrix( in vec3 normal, in mat4 viewMatrix ) {\n\treturn normalize( ( vec4( normal, 0.0 ) * viewMatrix ).xyz );\n}\nvec3 transformDirectionByInverseViewMatrix( in vec3 dir, in mat4 viewMatrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * viewMatrix ).xyz );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated";
344
344
 
345
- var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif";
346
-
347
345
  var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz;\n#endif";
348
346
 
349
347
  var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";
@@ -360,7 +358,7 @@ var colorspace_pars_fragment = "vec4 LinearTransferOETF( in vec4 value ) {\n\tre
360
358
 
361
359
  var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = transformNormalByInverseViewMatrix( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, envMapRotation * reflectVec );\n\t\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t\t#endif\n\t#endif\n#endif";
362
360
 
363
- var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform mat3 envMapRotation;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n#endif";
361
+ var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform mat3 envMapRotation;\n\tuniform samplerCube envMap;\n\t#ifdef ENVMAP_TYPE_PMREM\n\t\tfloat roughnessToMip( const in float roughness ) {\n\t\t\tfloat r = clamp( roughness, 0.0, 1.0 );\n\t\t\treturn ENVMAP_MAX_LOD * r * ( 2.0 - r );\n\t\t}\n\t#endif\n#endif";
364
362
 
365
363
  var envmap_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif";
366
364
 
@@ -386,7 +384,7 @@ var lights_lambert_pars_fragment = "varying vec3 vViewPosition;\nstruct LambertM
386
384
 
387
385
  var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = transformNormalByInverseViewMatrix( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_SUN_LIGHTS > 0\n\tstruct SunLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform SunLight sunLights[ NUM_SUN_LIGHTS ];\n\tvoid getSunLightInfo( const in SunLight sunLight, out IncidentLight light ) {\n\t\tlight.color = sunLight.color;\n\t\tlight.direction = sunLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif\n#include <lightprobes_pars_fragment>";
388
386
 
389
- var envmap_physical_pars_fragment = "#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = transformNormalByInverseViewMatrix( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, pow4( roughness ) ) );\n\t\t\treflectVec = transformDirectionByInverseViewMatrix( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_RETROREFLECTION\n\t\tvec3 getIBLRetroRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 retroVec = normalize( mix( viewDir, normal, pow4( roughness ) ) );\n\t\t\t\tretroVec = transformDirectionByInverseViewMatrix( retroVec, viewMatrix );\n\t\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * retroVec, roughness );\n\t\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t\t#ifdef USE_RETROREFLECTION\n\t\t\tvec3 getIBLAnisotropyRetroRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\t\treturn getIBLRetroRadiance( viewDir, bentNormal, roughness );\n\t\t\t\t#else\n\t\t\t\t\treturn vec3( 0.0 );\n\t\t\t\t#endif\n\t\t\t}\n\t\t#endif\n\t#endif\n#endif";
387
+ var envmap_physical_pars_fragment = "#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_PMREM\n\t\t\tvec3 worldNormal = transformNormalByInverseViewMatrix( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureLod( envMap, envMapRotation * worldNormal, ENVMAP_MAX_LOD );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_PMREM\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, pow4( roughness ) ) );\n\t\t\treflectVec = transformDirectionByInverseViewMatrix( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureLod( envMap, envMapRotation * reflectVec, roughnessToMip( roughness ) );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_RETROREFLECTION\n\t\tvec3 getIBLRetroRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t\t#ifdef ENVMAP_TYPE_PMREM\n\t\t\t\tvec3 retroVec = normalize( mix( viewDir, normal, pow4( roughness ) ) );\n\t\t\t\tretroVec = transformDirectionByInverseViewMatrix( retroVec, viewMatrix );\n\t\t\t\tvec4 envMapColor = textureLod( envMap, envMapRotation * retroVec, roughnessToMip( roughness ) );\n\t\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_PMREM\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t\t#ifdef USE_RETROREFLECTION\n\t\t\tvec3 getIBLAnisotropyRetroRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t\t#ifdef ENVMAP_TYPE_PMREM\n\t\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\t\treturn getIBLRetroRadiance( viewDir, bentNormal, roughness );\n\t\t\t\t#else\n\t\t\t\t\treturn vec3( 0.0 );\n\t\t\t\t#endif\n\t\t\t}\n\t\t#endif\n\t#endif\n#endif";
390
388
 
391
389
  var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;";
392
390
 
@@ -396,17 +394,17 @@ var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor
396
394
 
397
395
  var lights_phong_pars_fragment = "varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong";
398
396
 
399
- var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.diffuseContribution = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.metalness = metalnessFactor;\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor;\n\tmaterial.specularColorBlended = mix( material.specularColor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = vec3( 0.04 );\n\tmaterial.specularColorBlended = mix( material.specularColor, diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_DISPERSION\n\tmaterial.dispersion = dispersion;\n#endif\n#ifdef USE_RETROREFLECTION\n\tmaterial.retroreflectivity = retroreflectivity;\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.0001, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif";
397
+ var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.diffuseContribution = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.metalness = metalnessFactor;\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.045 );\nmaterial.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef USE_DIFFUSE_ROUGHNESS\n\tfloat diffuseRoughnessFactor = diffuseRoughness;\n\t#ifdef USE_DIFFUSE_ROUGHNESSMAP\n\t\tdiffuseRoughnessFactor *= texture2D( diffuseRoughnessMap, vDiffuseRoughnessMapUv ).r;\n\t#endif\n\tmaterial.diffuseRoughness = saturate( diffuseRoughnessFactor );\n#endif\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor;\n\tmaterial.specularColorBlended = mix( material.specularColor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = vec3( 0.04 );\n\tmaterial.specularColorBlended = mix( material.specularColor, diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.045 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_DISPERSION\n\tmaterial.dispersion = dispersion;\n#endif\n#ifdef USE_RETROREFLECTION\n\tmaterial.retroreflectivity = retroreflectivity;\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.0001, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif";
400
398
 
401
- var lights_physical_pars_fragment = "uniform sampler2D dfgLUT;\nstruct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tvec3 diffuseContribution;\n\tvec3 specularColor;\n\tvec3 specularColorBlended;\n\tfloat roughness;\n\tfloat metalness;\n\tfloat specularF90;\n\tfloat dispersion;\n\tvec2 dfg;\n\tvec3 multiScatteringCompensation;\n\t#ifdef USE_RETROREFLECTION\n\t\tfloat retroreflectivity;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0Dielectric;\n\t\tvec3 iridescenceF0Metallic;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\treturn 0.5 / max( gv + gl, EPSILON );\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColorBlended;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transpose( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat rInv = 1.0 / ( roughness + 0.1 );\n\tfloat a = -1.9362 + 1.0678 * roughness + 0.4573 * r2 - 0.8469 * rInv;\n\tfloat b = -0.6014 + 0.5538 * roughness - 0.4670 * r2 - 0.1255 * rInv;\n\tfloat DG = exp( a * dotNV + b );\n\treturn saturate( DG );\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 fab = texture2D( dfgLUT, vec2( roughness, dotNV ) ).rg;\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec2 fab, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec2 fab, const in vec3 specularColor, const in float specularF90, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColorBlended * t2.x + ( material.specularF90 - material.specularColorBlended ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseContribution * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t\t#ifdef USE_CLEARCOAT\n\t\t\tvec3 Ncc = geometryClearcoatNormal;\n\t\t\tvec2 uvClearcoat = LTC_Uv( Ncc, viewDir, material.clearcoatRoughness );\n\t\t\tvec4 t1Clearcoat = texture2D( ltc_1, uvClearcoat );\n\t\t\tvec4 t2Clearcoat = texture2D( ltc_2, uvClearcoat );\n\t\t\tmat3 mInvClearcoat = mat3(\n\t\t\t\tvec3( t1Clearcoat.x, 0, t1Clearcoat.y ),\n\t\t\t\tvec3( 0, 1, 0 ),\n\t\t\t\tvec3( t1Clearcoat.z, 0, t1Clearcoat.w )\n\t\t\t);\n\t\t\tvec3 fresnelClearcoat = material.clearcoatF0 * t2Clearcoat.x + ( material.clearcoatF90 - material.clearcoatF0 ) * t2Clearcoat.y;\n\t\t\tclearcoatSpecularDirect += lightColor * fresnelClearcoat * LTC_Evaluate( Ncc, viewDir, position, mInvClearcoat, rectCoords );\n\t\t#endif\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n \n \t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n \n \t\tfloat sheenAlbedoV = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n \t\tfloat sheenAlbedoL = IBLSheenBRDF( geometryNormal, directLight.direction, material.sheenRoughness );\n \n \t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * max( sheenAlbedoV, sheenAlbedoL );\n \n \t\tirradiance *= sheenEnergyComp;\n \n \t#endif\n\tvec3 specularBRDF = BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\t#ifdef USE_RETROREFLECTION\n\t\tvec3 retroViewDir = reflect( - geometryViewDir, geometryNormal );\n\t\tvec3 retroSpecularBRDF = BRDF_GGX( directLight.direction, retroViewDir, geometryNormal, material );\n\t\tspecularBRDF = mix( specularBRDF, retroSpecularBRDF, saturate( material.retroreflectivity ) );\n\t#endif\n\treflectedLight.directSpecular += irradiance * specularBRDF * material.multiScatteringCompensation;\n\tvec3 halfDir = normalize( directLight.direction + geometryViewDir );\n\tfloat dotVH = saturate( dot( geometryViewDir, halfDir ) );\n\tvec3 F = F_Schlick( material.specularColor, material.specularF90, dotVH );\n\t#ifdef USE_RETROREFLECTION\n\t\tvec3 retroHalfDir = normalize( directLight.direction + retroViewDir );\n\t\tfloat dotRetroVH = saturate( dot( retroViewDir, retroHalfDir ) );\n\t\tvec3 retroF = F_Schlick( material.specularColor, material.specularF90, dotRetroVH );\n\t\tF = mix( F, retroF, saturate( material.retroreflectivity ) );\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseContribution ) * ( 1.0 - F );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( material.dfg, material.specularColor, material.specularF90, material.iridescence, material.iridescenceF0Dielectric, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( material.dfg, material.specularColor, material.specularF90, singleScattering, multiScattering );\n\t#endif\n\tvec3 diffuse = irradiance * BRDF_Lambert( material.diffuseContribution ) * ( 1.0 - singleScattering - multiScattering );\n\t#ifdef USE_SHEEN\n\t\tfloat sheenAlbedo = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * sheenAlbedo * RECIPROCAL_PI;\n\t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * sheenAlbedo;\n\t\tdiffuse *= sheenEnergyComp;\n\t#endif\n\treflectedLight.indirectDiffuse += diffuse;\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness ) * RECIPROCAL_PI;\n \t#endif\n\tvec3 singleScatteringDielectric = vec3( 0.0 );\n\tvec3 multiScatteringDielectric = vec3( 0.0 );\n\tvec3 singleScatteringMetallic = vec3( 0.0 );\n\tvec3 multiScatteringMetallic = vec3( 0.0 );\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( material.dfg, material.specularColor, material.specularF90, material.iridescence, material.iridescenceF0Dielectric, singleScatteringDielectric, multiScatteringDielectric );\n\t\tcomputeMultiscatteringIridescence( material.dfg, material.diffuseColor, material.specularF90, material.iridescence, material.iridescenceF0Metallic, singleScatteringMetallic, multiScatteringMetallic );\n\t#else\n\t\tcomputeMultiscattering( material.dfg, material.specularColor, material.specularF90, singleScatteringDielectric, multiScatteringDielectric );\n\t\tcomputeMultiscattering( material.dfg, material.diffuseColor, material.specularF90, singleScatteringMetallic, multiScatteringMetallic );\n\t#endif\n\tvec3 singleScattering = mix( singleScatteringDielectric, singleScatteringMetallic, material.metalness );\n\tvec3 multiScattering = mix( multiScatteringDielectric, multiScatteringMetallic, material.metalness );\n\tvec3 totalScatteringDielectric = singleScatteringDielectric + multiScatteringDielectric;\n\tvec3 diffuse = material.diffuseContribution * ( 1.0 - totalScatteringDielectric );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tvec3 indirectSpecular = radiance * singleScattering;\n\tindirectSpecular += multiScattering * cosineWeightedIrradiance;\n\tvec3 indirectDiffuse = diffuse * cosineWeightedIrradiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenAlbedo = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * sheenAlbedo;\n\t\tindirectSpecular *= sheenEnergyComp;\n\t\tindirectDiffuse *= sheenEnergyComp;\n\t#endif\n\treflectedLight.indirectSpecular += indirectSpecular;\n\treflectedLight.indirectDiffuse += indirectDiffuse;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}";
399
+ var lights_physical_pars_fragment = "uniform sampler2D dfgLUT;\nstruct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tvec3 diffuseContribution;\n\tvec3 specularColor;\n\tvec3 specularColorBlended;\n\tfloat roughness;\n\tfloat metalness;\n\tfloat specularF90;\n\tfloat dispersion;\n\tvec2 dfg;\n\tvec3 multiScatteringCompensation;\n\t#ifdef USE_DIFFUSE_ROUGHNESS\n\t\tfloat diffuseRoughness;\n\t#endif\n\t#ifdef USE_RETROREFLECTION\n\t\tfloat retroreflectivity;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0Dielectric;\n\t\tvec3 iridescenceF0Metallic;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\n#ifdef USE_DIFFUSE_ROUGHNESS\n\tconst float EON_EPSILON = 1e-7;\n\tfloat FON_DirectionalAlbedo( const in float mu, const in float roughness, const in float A ) {\n\t\tfloat muComp = 1.0 - mu;\n\t\tfloat gOverPi = muComp * ( 0.0571085289 + muComp * ( 0.491881867 + muComp * ( - 0.332181442 + muComp * 0.0714429953 ) ) );\n\t\treturn A * ( 1.0 + roughness * gOverPi );\n\t}\n\tvec3 BRDF_EON( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 diffuseColor, const in float roughness ) {\n\t\tvec3 rho = saturate( diffuseColor );\n\t\tif ( roughness <= EON_EPSILON ) return BRDF_Lambert( rho );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat s = dot( lightDir, viewDir ) - dotNL * dotNV;\n\t\tfloat sOverT = ( s > 0.0 ) ? s / max( max( dotNL, dotNV ), EON_EPSILON ) : s;\n\t\tfloat A = 1.0 / ( 1.0 + ( 0.5 - 2.0 / ( 3.0 * PI ) ) * roughness );\n\t\tvec3 singleScatter = rho * RECIPROCAL_PI * A * ( 1.0 + roughness * sOverT );\n\t\tfloat averageAlbedo = A * ( 1.0 + ( 2.0 / 3.0 - 28.0 / ( 15.0 * PI ) ) * roughness );\n\t\tfloat albedoV = FON_DirectionalAlbedo( dotNV, roughness, A );\n\t\tfloat albedoL = FON_DirectionalAlbedo( dotNL, roughness, A );\n\t\tvec3 rhoMultiScatter = rho * rho * averageAlbedo / max( vec3( EON_EPSILON ), vec3( 1.0 ) - rho * ( 1.0 - averageAlbedo ) );\n\t\tvec3 multiScatter = rhoMultiScatter * RECIPROCAL_PI\n\t\t\t* max( EON_EPSILON, 1.0 - albedoV )\n\t\t\t* max( EON_EPSILON, 1.0 - albedoL )\n\t\t\t/ max( EON_EPSILON, 1.0 - averageAlbedo );\n\t\treturn singleScatter + multiScatter;\n\t}\n\tvec3 EON_DirectionalAlbedo( const in vec3 diffuseColor, const in float roughness, const in float dotNV ) {\n\t\tvec3 rho = saturate( diffuseColor );\n\t\tif ( roughness <= EON_EPSILON ) return rho;\n\t\tfloat A = 1.0 / ( 1.0 + ( 0.5 - 2.0 / ( 3.0 * PI ) ) * roughness );\n\t\tfloat directionalAlbedo = FON_DirectionalAlbedo( dotNV, roughness, A );\n\t\tfloat averageAlbedo = A * ( 1.0 + ( 2.0 / 3.0 - 28.0 / ( 15.0 * PI ) ) * roughness );\n\t\tvec3 rhoMultiScatter = rho * rho * averageAlbedo / max( vec3( EON_EPSILON ), vec3( 1.0 ) - rho * ( 1.0 - averageAlbedo ) );\n\t\treturn rho * directionalAlbedo + rhoMultiScatter * ( 1.0 - directionalAlbedo );\n\t}\n#endif\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\treturn 0.5 / max( gv + gl, EPSILON );\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = max( material.clearcoatRoughness, 0.045 );\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColorBlended;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = max( material.roughness, 0.045 );\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat alphaT = max( material.alphaT, alpha );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transpose( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat rInv = 1.0 / ( roughness + 0.1 );\n\tfloat a = -1.9362 + 1.0678 * roughness + 0.4573 * r2 - 0.8469 * rInv;\n\tfloat b = -0.6014 + 0.5538 * roughness - 0.4670 * r2 - 0.1255 * rInv;\n\tfloat DG = exp( a * dotNV + b );\n\treturn saturate( DG );\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 fab = texture2D( dfgLUT, vec2( roughness, dotNV ) ).rg;\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec2 fab, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec2 fab, const in vec3 specularColor, const in float specularF90, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColorBlended * t2.x + ( material.specularF90 - material.specularColorBlended ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseContribution * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t\t#ifdef USE_CLEARCOAT\n\t\t\tvec3 Ncc = geometryClearcoatNormal;\n\t\t\tvec2 uvClearcoat = LTC_Uv( Ncc, viewDir, material.clearcoatRoughness );\n\t\t\tvec4 t1Clearcoat = texture2D( ltc_1, uvClearcoat );\n\t\t\tvec4 t2Clearcoat = texture2D( ltc_2, uvClearcoat );\n\t\t\tmat3 mInvClearcoat = mat3(\n\t\t\t\tvec3( t1Clearcoat.x, 0, t1Clearcoat.y ),\n\t\t\t\tvec3( 0, 1, 0 ),\n\t\t\t\tvec3( t1Clearcoat.z, 0, t1Clearcoat.w )\n\t\t\t);\n\t\t\tvec3 fresnelClearcoat = material.clearcoatF0 * t2Clearcoat.x + ( material.clearcoatF90 - material.clearcoatF0 ) * t2Clearcoat.y;\n\t\t\tclearcoatSpecularDirect += lightColor * fresnelClearcoat * LTC_Evaluate( Ncc, viewDir, position, mInvClearcoat, rectCoords );\n\t\t#endif\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n \n \t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n \n \t\tfloat sheenAlbedoV = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n \t\tfloat sheenAlbedoL = IBLSheenBRDF( geometryNormal, directLight.direction, material.sheenRoughness );\n \n \t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * max( sheenAlbedoV, sheenAlbedoL );\n \n \t\tirradiance *= sheenEnergyComp;\n \n \t#endif\n\tvec3 specularBRDF = BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\t#ifdef USE_RETROREFLECTION\n\t\tvec3 retroViewDir = reflect( - geometryViewDir, geometryNormal );\n\t\tvec3 retroSpecularBRDF = BRDF_GGX( directLight.direction, retroViewDir, geometryNormal, material );\n\t\tspecularBRDF = mix( specularBRDF, retroSpecularBRDF, saturate( material.retroreflectivity ) );\n\t#endif\n\treflectedLight.directSpecular += irradiance * specularBRDF * material.multiScatteringCompensation;\n\tvec3 halfDir = normalize( directLight.direction + geometryViewDir );\n\tfloat dotVH = saturate( dot( geometryViewDir, halfDir ) );\n\tvec3 F = F_Schlick( material.specularColor, material.specularF90, dotVH );\n\t#ifdef USE_RETROREFLECTION\n\t\tvec3 retroHalfDir = normalize( directLight.direction + retroViewDir );\n\t\tfloat dotRetroVH = saturate( dot( retroViewDir, retroHalfDir ) );\n\t\tvec3 retroF = F_Schlick( material.specularColor, material.specularF90, dotRetroVH );\n\t\tF = mix( F, retroF, saturate( material.retroreflectivity ) );\n\t#endif\n\t#ifdef USE_DIFFUSE_ROUGHNESS\n\t\tvec3 diffuseBRDF = BRDF_EON( directLight.direction, geometryViewDir, geometryNormal, material.diffuseColor, material.diffuseRoughness ) * ( 1.0 - material.metalness );\n\t#else\n\t\tvec3 diffuseBRDF = BRDF_Lambert( material.diffuseContribution );\n\t#endif\n\treflectedLight.directDiffuse += irradiance * diffuseBRDF * ( 1.0 - F );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( material.dfg, material.specularColor, material.specularF90, material.iridescence, material.iridescenceF0Dielectric, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( material.dfg, material.specularColor, material.specularF90, singleScattering, multiScattering );\n\t#endif\n\t#ifdef USE_DIFFUSE_ROUGHNESS\n\t\tfloat dotNV = saturate( dot( geometryNormal, geometryViewDir ) );\n\t\tvec3 diffuseAlbedo = EON_DirectionalAlbedo( material.diffuseColor, material.diffuseRoughness, dotNV ) * ( 1.0 - material.metalness );\n\t\tvec3 diffuse = irradiance * RECIPROCAL_PI * diffuseAlbedo * ( 1.0 - singleScattering - multiScattering );\n\t#else\n\t\tvec3 diffuse = irradiance * BRDF_Lambert( material.diffuseContribution ) * ( 1.0 - singleScattering - multiScattering );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tfloat sheenAlbedo = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * sheenAlbedo * RECIPROCAL_PI;\n\t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * sheenAlbedo;\n\t\tdiffuse *= sheenEnergyComp;\n\t#endif\n\treflectedLight.indirectDiffuse += diffuse;\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness ) * RECIPROCAL_PI;\n \t#endif\n\tvec3 singleScatteringDielectric = vec3( 0.0 );\n\tvec3 multiScatteringDielectric = vec3( 0.0 );\n\tvec3 singleScatteringMetallic = vec3( 0.0 );\n\tvec3 multiScatteringMetallic = vec3( 0.0 );\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( material.dfg, material.specularColor, material.specularF90, material.iridescence, material.iridescenceF0Dielectric, singleScatteringDielectric, multiScatteringDielectric );\n\t\tcomputeMultiscatteringIridescence( material.dfg, material.diffuseColor, material.specularF90, material.iridescence, material.iridescenceF0Metallic, singleScatteringMetallic, multiScatteringMetallic );\n\t#else\n\t\tcomputeMultiscattering( material.dfg, material.specularColor, material.specularF90, singleScatteringDielectric, multiScatteringDielectric );\n\t\tcomputeMultiscattering( material.dfg, material.diffuseColor, material.specularF90, singleScatteringMetallic, multiScatteringMetallic );\n\t#endif\n\tvec3 singleScattering = mix( singleScatteringDielectric, singleScatteringMetallic, material.metalness );\n\tvec3 multiScattering = mix( multiScatteringDielectric, multiScatteringMetallic, material.metalness );\n\tvec3 totalScatteringDielectric = singleScatteringDielectric + multiScatteringDielectric;\n\t#ifdef USE_DIFFUSE_ROUGHNESS\n\t\tfloat dotNV = saturate( dot( geometryNormal, geometryViewDir ) );\n\t\tvec3 diffuse = EON_DirectionalAlbedo( material.diffuseColor, material.diffuseRoughness, dotNV ) * ( 1.0 - material.metalness ) * ( 1.0 - totalScatteringDielectric );\n\t#else\n\t\tvec3 diffuse = material.diffuseContribution * ( 1.0 - totalScatteringDielectric );\n\t#endif\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tvec3 indirectSpecular = radiance * singleScattering;\n\tindirectSpecular += multiScattering * cosineWeightedIrradiance;\n\tvec3 indirectDiffuse = diffuse * cosineWeightedIrradiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenAlbedo = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * sheenAlbedo;\n\t\tindirectSpecular *= sheenEnergyComp;\n\t\tindirectDiffuse *= sheenEnergyComp;\n\t#endif\n\treflectedLight.indirectSpecular += indirectSpecular;\n\treflectedLight.indirectDiffuse += indirectDiffuse;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}";
402
400
 
403
- var lights_fragment_begin = "\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tvec3 iridescenceFresnelDielectric = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tvec3 iridescenceFresnelMetallic = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.diffuseColor );\n\t\tmaterial.iridescenceFresnel = mix( iridescenceFresnelDielectric, iridescenceFresnelMetallic, material.metalness );\n\t\tmaterial.iridescenceF0Dielectric = Schlick_to_F0( iridescenceFresnelDielectric, 1.0, dotNVi );\n\t\tmaterial.iridescenceF0Metallic = Schlick_to_F0( iridescenceFresnelMetallic, 1.0, dotNVi );\n\t}\n#endif\n#ifdef STANDARD\n\tfloat dotNVms = saturate( dot( geometryNormal, geometryViewDir ) );\n\tmaterial.dfg = texture2D( dfgLUT, vec2( material.roughness, dotNVms ) ).rg;\n\t#if ( NUM_SUN_LIGHTS > 0 || NUM_DIR_LIGHTS > 0 || NUM_POINT_LIGHTS > 0 || NUM_SPOT_LIGHTS > 0 )\n\t\tfloat EssMs = material.dfg.x + material.dfg.y;\n\t\tmaterial.multiScatteringCompensation = 1.0 + material.specularColorBlended * ( 1.0 / EssMs - 1.0 );\n\t#endif\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS ) && ( defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_BASIC ) )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SUN_LIGHTS > 0 ) && defined( RE_Direct )\n\tSunLight sunLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SUN_LIGHT_SHADOWS > 0\n\tSunLightShadow sunLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SUN_LIGHTS; i ++ ) {\n\t\tsunLight = sunLights[ i ];\n\t\tgetSunLightInfo( sunLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SUN_LIGHT_SHADOWS )\n\t\tsunLightShadow = sunLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getSunShadow( sunShadowMap[ i ], sunLightShadow, UNROLLED_LOOP_INDEX ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#ifdef USE_LIGHT_PROBES_GRID\n\t\tvec3 probeWorldPos = ( ( vec4( geometryPosition, 1.0 ) - viewMatrix[ 3 ] ) * viewMatrix ).xyz;\n\t\tvec3 probeWorldNormal = transformNormalByInverseViewMatrix( geometryNormal, viewMatrix );\n\t\tirradiance += getLightProbeGridIrradiance( probeWorldPos, probeWorldNormal );\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif";
401
+ var lights_fragment_begin = "\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tvec3 iridescenceFresnelDielectric = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tvec3 iridescenceFresnelMetallic = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.diffuseColor );\n\t\tmaterial.iridescenceFresnel = mix( iridescenceFresnelDielectric, iridescenceFresnelMetallic, material.metalness );\n\t\tmaterial.iridescenceF0Dielectric = Schlick_to_F0( iridescenceFresnelDielectric, 1.0, dotNVi );\n\t\tmaterial.iridescenceF0Metallic = Schlick_to_F0( iridescenceFresnelMetallic, 1.0, dotNVi );\n\t}\n#endif\n#ifdef STANDARD\n\tfloat dotNVms = saturate( dot( geometryNormal, geometryViewDir ) );\n\tmaterial.dfg = texture2D( dfgLUT, vec2( material.roughness, dotNVms ) ).rg;\n\t#if ( NUM_SUN_LIGHTS > 0 || NUM_DIR_LIGHTS > 0 || NUM_POINT_LIGHTS > 0 || NUM_SPOT_LIGHTS > 0 )\n\t\tfloat EssMs = material.dfg.x + material.dfg.y;\n\t\tmaterial.multiScatteringCompensation = 1.0 + material.specularColorBlended * ( 1.0 / EssMs - 1.0 );\n\t#endif\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS ) && ( defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_BASIC ) )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SUN_LIGHTS > 0 ) && defined( RE_Direct )\n\tSunLight sunLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SUN_LIGHT_SHADOWS > 0\n\tSunLightShadow sunLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SUN_LIGHTS; i ++ ) {\n\t\tsunLight = sunLights[ i ];\n\t\tgetSunLightInfo( sunLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SUN_LIGHT_SHADOWS )\n\t\tsunLightShadow = sunLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getSunShadow( sunShadowMap[ i ], sunLightShadow, UNROLLED_LOOP_INDEX ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_LIGHT_PROBE_GRIDS > 0\n\t\tvec3 probeWorldPos = ( ( vec4( geometryPosition, 1.0 ) - viewMatrix[ 3 ] ) * viewMatrix ).xyz;\n\t\tvec3 probeWorldNormal = transformNormalByInverseViewMatrix( geometryNormal, viewMatrix );\n\t\tint probeGrid = - 1;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_LIGHT_PROBE_GRIDS; i ++ ) {\n\t\t\tif ( isInsideLightProbeGrid( probeWorldPos, probeWorldNormal, probesMin[ i ], probesMax[ i ], probesResolution[ i ] ) ) probeGrid = UNROLLED_LOOP_INDEX;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_LIGHT_PROBE_GRIDS; i ++ ) {\n\t\t\tif ( probeGrid == UNROLLED_LOOP_INDEX ) irradiance += getLightProbeGridIrradiance( probesSH[ i ], probesMin[ i ], probesMax[ i ], probesResolution[ i ], probeWorldPos, probeWorldNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif";
404
402
 
405
- var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\t#if defined( STANDARD ) || defined( LAMBERT ) || defined( PHONG )\n\t\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t\t#endif\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 iblRadiance = getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tvec3 iblRadiance = getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_RETROREFLECTION\n\t\t#ifdef USE_ANISOTROPY\n\t\t\tvec3 retroIBLRadiance = getIBLAnisotropyRetroRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t\t#else\n\t\t\tvec3 retroIBLRadiance = getIBLRetroRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t\t#endif\n\t\tiblRadiance = mix( iblRadiance, retroIBLRadiance, saturate( material.retroreflectivity ) );\n\t#endif\n\tradiance += iblRadiance;\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif";
403
+ var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( ENVMAP_TYPE_PMREM )\n\t\t#if defined( STANDARD ) || defined( LAMBERT ) || defined( PHONG )\n\t\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t\t#endif\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 iblRadiance = getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tvec3 iblRadiance = getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_RETROREFLECTION\n\t\t#ifdef USE_ANISOTROPY\n\t\t\tvec3 retroIBLRadiance = getIBLAnisotropyRetroRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t\t#else\n\t\t\tvec3 retroIBLRadiance = getIBLRetroRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t\t#endif\n\t\tiblRadiance = mix( iblRadiance, retroIBLRadiance, saturate( material.retroreflectivity ) );\n\t#endif\n\tradiance += iblRadiance;\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif";
406
404
 
407
405
  var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\t#if defined( LAMBERT ) || defined( PHONG )\n\t\tirradiance += iblIrradiance;\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif";
408
406
 
409
- var lightprobes_pars_fragment = "#ifdef USE_LIGHT_PROBES_GRID\nuniform highp sampler3D probesSH;\nuniform vec3 probesMin;\nuniform vec3 probesMax;\nuniform vec3 probesResolution;\nvec3 getLightProbeGridIrradiance( vec3 worldPos, vec3 worldNormal ) {\n\tvec3 res = probesResolution;\n\tvec3 gridRange = probesMax - probesMin;\n\tvec3 resMinusOne = res - 1.0;\n\tvec3 probeSpacing = gridRange / resMinusOne;\n\tvec3 samplePos = worldPos + worldNormal * probeSpacing * 0.5;\n\tvec3 uvw = clamp( ( samplePos - probesMin ) / gridRange, 0.0, 1.0 );\n\tuvw = uvw * resMinusOne / res + 0.5 / res;\n\tfloat nz = res.z;\n\tfloat paddedSlices = nz + 2.0;\n\tfloat atlasDepth = 7.0 * paddedSlices;\n\tfloat uvZBase = uvw.z * nz + 1.0;\n\tvec4 s0 = texture( probesSH, vec3( uvw.xy, ( uvZBase ) / atlasDepth ) );\n\tvec4 s1 = texture( probesSH, vec3( uvw.xy, ( uvZBase + paddedSlices ) / atlasDepth ) );\n\tvec4 s2 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 2.0 * paddedSlices ) / atlasDepth ) );\n\tvec4 s3 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 3.0 * paddedSlices ) / atlasDepth ) );\n\tvec4 s4 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 4.0 * paddedSlices ) / atlasDepth ) );\n\tvec4 s5 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 5.0 * paddedSlices ) / atlasDepth ) );\n\tvec4 s6 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 6.0 * paddedSlices ) / atlasDepth ) );\n\tvec3 c0 = s0.xyz;\n\tvec3 c1 = vec3( s0.w, s1.xy );\n\tvec3 c2 = vec3( s1.zw, s2.x );\n\tvec3 c3 = s2.yzw;\n\tvec3 c4 = s3.xyz;\n\tvec3 c5 = vec3( s3.w, s4.xy );\n\tvec3 c6 = vec3( s4.zw, s5.x );\n\tvec3 c7 = s5.yzw;\n\tvec3 c8 = s6.xyz;\n\tfloat x = worldNormal.x, y = worldNormal.y, z = worldNormal.z;\n\tvec3 result = c0 * 0.886227;\n\tresult += c1 * 2.0 * 0.511664 * y;\n\tresult += c2 * 2.0 * 0.511664 * z;\n\tresult += c3 * 2.0 * 0.511664 * x;\n\tresult += c4 * 2.0 * 0.429043 * x * y;\n\tresult += c5 * 2.0 * 0.429043 * y * z;\n\tresult += c6 * ( 0.743125 * z * z - 0.247708 );\n\tresult += c7 * 2.0 * 0.429043 * x * z;\n\tresult += c8 * 0.429043 * ( x * x - y * y );\n\treturn max( result, vec3( 0.0 ) );\n}\n#endif";
407
+ var lightprobes_pars_fragment = "#if NUM_LIGHT_PROBE_GRIDS > 0\nuniform highp sampler3D probesSH[ NUM_LIGHT_PROBE_GRIDS ];\nuniform vec3 probesMin[ NUM_LIGHT_PROBE_GRIDS ];\nuniform vec3 probesMax[ NUM_LIGHT_PROBE_GRIDS ];\nuniform vec3 probesResolution[ NUM_LIGHT_PROBE_GRIDS ];\nbool isInsideLightProbeGrid( vec3 worldPos, vec3 worldNormal, vec3 probesMin, vec3 probesMax, vec3 probesResolution ) {\n\tvec3 spacing = ( probesMax - probesMin ) / probesResolution;\n\tvec3 samplePos = worldPos + worldNormal * spacing * 0.5;\n\tvec3 margin = spacing * 0.01;\n\treturn all( greaterThanEqual( samplePos, probesMin - margin ) ) && all( lessThanEqual( samplePos, probesMax + margin ) );\n}\nvec3 getLightProbeGridIrradiance( highp sampler3D probesSH, vec3 probesMin, vec3 probesMax, vec3 probesResolution, vec3 worldPos, vec3 worldNormal ) {\n\tvec3 res = probesResolution;\n\tvec3 gridRange = probesMax - probesMin;\n\tvec3 probeSpacing = gridRange / res;\n\tvec3 samplePos = worldPos + worldNormal * probeSpacing * 0.5;\n\tvec3 uvw = clamp( ( samplePos - probesMin ) / gridRange, 0.5 / res, 1.0 - 0.5 / res );\n\tfloat nz = res.z;\n\tfloat paddedSlices = nz + 2.0;\n\tfloat atlasDepth = 7.0 * paddedSlices;\n\tfloat uvZBase = uvw.z * nz + 1.0;\n\tvec4 s0 = texture( probesSH, vec3( uvw.xy, ( uvZBase ) / atlasDepth ) );\n\tvec4 s1 = texture( probesSH, vec3( uvw.xy, ( uvZBase + paddedSlices ) / atlasDepth ) );\n\tvec4 s2 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 2.0 * paddedSlices ) / atlasDepth ) );\n\tvec4 s3 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 3.0 * paddedSlices ) / atlasDepth ) );\n\tvec4 s4 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 4.0 * paddedSlices ) / atlasDepth ) );\n\tvec4 s5 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 5.0 * paddedSlices ) / atlasDepth ) );\n\tvec4 s6 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 6.0 * paddedSlices ) / atlasDepth ) );\n\tvec3 c0 = s0.xyz;\n\tvec3 c1 = vec3( s0.w, s1.xy );\n\tvec3 c2 = vec3( s1.zw, s2.x );\n\tvec3 c3 = s2.yzw;\n\tvec3 c4 = s3.xyz;\n\tvec3 c5 = vec3( s3.w, s4.xy );\n\tvec3 c6 = vec3( s4.zw, s5.x );\n\tvec3 c7 = s5.yzw;\n\tvec3 c8 = s6.xyz;\n\tfloat x = worldNormal.x, y = worldNormal.y, z = worldNormal.z;\n\tvec3 result = c0 * 0.886227;\n\tresult += c1 * 2.0 * 0.511664 * y;\n\tresult += c2 * 2.0 * 0.511664 * z;\n\tresult += c3 * 2.0 * 0.511664 * x;\n\tresult += c4 * 2.0 * 0.429043 * x * y;\n\tresult += c5 * 2.0 * 0.429043 * y * z;\n\tresult += c6 * ( 0.743125 * z * z - 0.247708 );\n\tresult += c7 * 2.0 * 0.429043 * x * z;\n\tresult += c8 * 0.429043 * ( x * x - y * y );\n\treturn max( result, vec3( 0.0 ) );\n}\n#endif";
410
408
 
411
409
  var logdepthbuf_fragment = "#if defined( USE_LOGARITHMIC_DEPTH_BUFFER )\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
412
410
 
@@ -430,7 +428,7 @@ var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D m
430
428
 
431
429
  var morphinstance_vertex = "#ifdef USE_INSTANCING_MORPH\n\tfloat morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\tfloat morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tmorphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r;\n\t}\n#endif";
432
430
 
433
- var morphcolor_vertex = "#if defined( USE_MORPHCOLORS )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif";
431
+ var morphcolor_vertex = "#if defined( USE_MORPHCOLORS )\n\t#if defined( USE_COLOR_ALPHA )\n\t\tvColor *= morphTargetBaseInfluence;\n\t#elif defined( USE_COLOR )\n\t\tvColor.rgb *= morphTargetBaseInfluence;\n\t#endif\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor.rgb += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif";
434
432
 
435
433
  var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif";
436
434
 
@@ -474,7 +472,7 @@ var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUG
474
472
 
475
473
  var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
476
474
 
477
- var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_SUN_LIGHT_SHADOWS > 0\n\t\t#define SUN_LIGHT_CASCADES 2\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform sampler2DShadow sunShadowMap[ NUM_SUN_LIGHT_SHADOWS ];\n\t\t#else\n\t\t\tuniform sampler2D sunShadowMap[ NUM_SUN_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tuniform mat4 sunShadowMatrix[ NUM_SUN_LIGHT_SHADOWS * SUN_LIGHT_CASCADES ];\n\t\tuniform vec4 sunShadowCascade[ NUM_SUN_LIGHT_SHADOWS * SUN_LIGHT_CASCADES ];\n\t\tvarying vec4 vSunShadowWorldPosition;\n\t\tvarying vec3 vSunShadowWorldNormal;\n\t\tstruct SunLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SunLightShadow sunLightShadows[ NUM_SUN_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform sampler2DShadow directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\t#else\n\t\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform sampler2DShadow spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\t#else\n\t\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform samplerCubeShadow pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\t#elif defined( SHADOWMAP_TYPE_BASIC )\n\t\t\tuniform samplerCube pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\tfloat interleavedGradientNoise( vec2 position ) {\n\t\t\treturn fract( 52.9829189 * fract( dot( position, vec2( 0.06711056, 0.00583715 ) ) ) );\n\t\t}\n\t\tvec2 vogelDiskSample( int sampleIndex, int samplesCount, float phi ) {\n\t\t\tconst float goldenAngle = 2.399963229728653;\n\t\t\tfloat r = sqrt( ( float( sampleIndex ) + 0.5 ) / float( samplesCount ) );\n\t\t\tfloat theta = float( sampleIndex ) * goldenAngle + phi;\n\t\t\treturn vec2( cos( theta ), sin( theta ) ) * r;\n\t\t}\n\t#endif\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\tfloat getShadow( sampler2DShadow shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\tshadowCoord.z += shadowBias;\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\t\tfloat radius = shadowRadius * texelSize.x;\n\t\t\t\tfloat phi = interleavedGradientNoise( gl_FragCoord.xy ) * PI2;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 0, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 1, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 2, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 3, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 4, 5, phi ) * radius, shadowCoord.z ) )\n\t\t\t\t) * 0.2;\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tshadowCoord.z -= shadowBias;\n\t\t\t#else\n\t\t\t\tshadowCoord.z += shadowBias;\n\t\t\t#endif\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tvec2 distribution = texture2D( shadowMap, shadowCoord.xy ).rg;\n\t\t\t\tfloat mean = distribution.x;\n\t\t\t\tfloat variance = distribution.y * distribution.y;\n\t\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\t\tfloat hard_shadow = step( mean, shadowCoord.z );\n\t\t\t\t#else\n\t\t\t\t\tfloat hard_shadow = step( shadowCoord.z, mean );\n\t\t\t\t#endif\n\t\t\t\t\n\t\t\t\tif ( hard_shadow == 1.0 ) {\n\t\t\t\t\tshadow = 1.0;\n\t\t\t\t} else {\n\t\t\t\t\tvariance = max( variance, 0.0000001 );\n\t\t\t\t\tfloat d = shadowCoord.z - mean;\n\t\t\t\t\tfloat p_max = variance / ( variance + d * d );\n\t\t\t\t\tp_max = clamp( ( p_max - 0.3 ) / 0.65, 0.0, 1.0 );\n\t\t\t\t\tshadow = max( hard_shadow, p_max );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#else\n\t\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tshadowCoord.z -= shadowBias;\n\t\t\t#else\n\t\t\t\tshadowCoord.z += shadowBias;\n\t\t\t#endif\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tfloat depth = texture2D( shadowMap, shadowCoord.xy ).r;\n\t\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\t\tshadow = step( depth, shadowCoord.z );\n\t\t\t\t#else\n\t\t\t\t\tshadow = step( shadowCoord.z, depth );\n\t\t\t\t#endif\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#endif\n\t#if NUM_SUN_LIGHT_SHADOWS > 0\n\t\tfloat getSunShadow(\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\t\tsampler2DShadow shadowMap,\n\t\t\t#else\n\t\t\t\tsampler2D shadowMap,\n\t\t\t#endif\n\t\t\tSunLightShadow sunLightShadow,\n\t\t\tint shadowIndex\n\t\t) {\n\t\t\tvec4 shadowWorldPosition = vec4( vSunShadowWorldPosition.xyz + vSunShadowWorldNormal * sunLightShadow.shadowNormalBias, 1.0 );\n\t\t\tfloat viewDepth = vSunShadowWorldPosition.w;\n\t\t\tint cascadeOffset = shadowIndex * SUN_LIGHT_CASCADES;\n\t\t\tfloat shadow = 1.0;\n\t\t\tfor ( int i = SUN_LIGHT_CASCADES - 1; i >= 0; i -- ) {\n\t\t\t\tvec4 cascade = sunShadowCascade[ cascadeOffset + i ];\n\t\t\t\tif ( viewDepth >= cascade.x && viewDepth < cascade.y ) {\n\t\t\t\t\tfloat cascadeShadow = getShadow(\n\t\t\t\t\t\tshadowMap,\n\t\t\t\t\t\tsunLightShadow.shadowMapSize,\n\t\t\t\t\t\tsunLightShadow.shadowIntensity,\n\t\t\t\t\t\tsunLightShadow.shadowBias,\n\t\t\t\t\t\tsunLightShadow.shadowRadius,\n\t\t\t\t\t\tsunShadowMatrix[ cascadeOffset + i ] * shadowWorldPosition\n\t\t\t\t\t);\n\t\t\t\t\tshadow = mix( cascadeShadow, shadow, smoothstep( cascade.z, cascade.y, viewDepth ) );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn shadow;\n\t\t}\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\tfloat getPointShadow( samplerCubeShadow shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\tvec3 absVec = abs( lightToPosition );\n\t\tfloat viewSpaceZ = max( max( absVec.x, absVec.y ), absVec.z );\n\t\tif ( viewSpaceZ - shadowCameraFar <= 0.0 && viewSpaceZ - shadowCameraNear >= 0.0 ) {\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tfloat dp = ( shadowCameraNear * ( shadowCameraFar - viewSpaceZ ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );\n\t\t\t\tdp -= shadowBias;\n\t\t\t#else\n\t\t\t\tfloat dp = ( shadowCameraFar * ( viewSpaceZ - shadowCameraNear ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );\n\t\t\t\tdp += shadowBias;\n\t\t\t#endif\n\t\t\tfloat texelSize = shadowRadius / shadowMapSize.x;\n\t\t\tvec3 absDir = abs( bd3D );\n\t\t\tvec3 tangent = absDir.x > absDir.z ? vec3( 0.0, 1.0, 0.0 ) : vec3( 1.0, 0.0, 0.0 );\n\t\t\ttangent = normalize( cross( bd3D, tangent ) );\n\t\t\tvec3 bitangent = cross( bd3D, tangent );\n\t\t\tfloat phi = interleavedGradientNoise( gl_FragCoord.xy ) * PI2;\n\t\t\tvec2 sample0 = vogelDiskSample( 0, 5, phi );\n\t\t\tvec2 sample1 = vogelDiskSample( 1, 5, phi );\n\t\t\tvec2 sample2 = vogelDiskSample( 2, 5, phi );\n\t\t\tvec2 sample3 = vogelDiskSample( 3, 5, phi );\n\t\t\tvec2 sample4 = vogelDiskSample( 4, 5, phi );\n\t\t\tshadow = (\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample0.x + bitangent * sample0.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample1.x + bitangent * sample1.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample2.x + bitangent * sample2.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample3.x + bitangent * sample3.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample4.x + bitangent * sample4.y ) * texelSize, dp ) )\n\t\t\t) * 0.2;\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\t#elif defined( SHADOWMAP_TYPE_BASIC )\n\tfloat getPointShadow( samplerCube shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tvec3 absVec = abs( lightToPosition );\n\t\tfloat viewSpaceZ = max( max( absVec.x, absVec.y ), absVec.z );\n\t\tif ( viewSpaceZ - shadowCameraFar <= 0.0 && viewSpaceZ - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( shadowCameraFar * ( viewSpaceZ - shadowCameraNear ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );\n\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tfloat depth = textureCube( shadowMap, bd3D ).r;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tdepth = 1.0 - depth;\n\t\t\t#endif\n\t\t\tshadow = step( dp, depth );\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\t#endif\n\t#endif\n#endif";
475
+ var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_SUN_LIGHT_SHADOWS > 0\n\t\t#define SUN_LIGHT_CASCADES 2\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform sampler2DShadow sunShadowMap[ NUM_SUN_LIGHT_SHADOWS ];\n\t\t#else\n\t\t\tuniform sampler2D sunShadowMap[ NUM_SUN_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tuniform mat4 sunShadowMatrix[ NUM_SUN_LIGHT_SHADOWS * SUN_LIGHT_CASCADES ];\n\t\tuniform vec4 sunShadowCascade[ NUM_SUN_LIGHT_SHADOWS * SUN_LIGHT_CASCADES ];\n\t\tvarying vec4 vSunShadowWorldPosition;\n\t\tvarying vec3 vSunShadowWorldNormal;\n\t\tstruct SunLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SunLightShadow sunLightShadows[ NUM_SUN_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform sampler2DShadow directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\t#else\n\t\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform sampler2DShadow spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\t#else\n\t\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform samplerCubeShadow pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\t#elif defined( SHADOWMAP_TYPE_BASIC )\n\t\t\tuniform samplerCube pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\tfloat interleavedGradientNoise( vec2 position ) {\n\t\t\treturn fract( 52.9829189 * fract( dot( position, vec2( 0.06711056, 0.00583715 ) ) ) );\n\t\t}\n\t\tvec2 vogelDiskSample( int sampleIndex, int samplesCount, float phi ) {\n\t\t\tconst float goldenAngle = 2.399963229728653;\n\t\t\tfloat r = sqrt( ( float( sampleIndex ) + 0.5 ) / float( samplesCount ) );\n\t\t\tfloat theta = float( sampleIndex ) * goldenAngle + phi;\n\t\t\treturn vec2( cos( theta ), sin( theta ) ) * r;\n\t\t}\n\t#endif\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\tfloat getShadow( sampler2DShadow shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tshadowCoord.z -= shadowBias;\n\t\t\t#else\n\t\t\t\tshadowCoord.z += shadowBias;\n\t\t\t#endif\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\t\tvec2 radius = shadowRadius * texelSize;\n\t\t\t\tfloat phi = interleavedGradientNoise( gl_FragCoord.xy ) * PI2;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 0, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 1, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 2, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 3, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 4, 5, phi ) * radius, shadowCoord.z ) )\n\t\t\t\t) * 0.2;\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tshadowCoord.z -= shadowBias;\n\t\t\t#else\n\t\t\t\tshadowCoord.z += shadowBias;\n\t\t\t#endif\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tvec2 distribution = texture2D( shadowMap, shadowCoord.xy ).rg;\n\t\t\t\tfloat mean = distribution.x;\n\t\t\t\tfloat variance = distribution.y * distribution.y;\n\t\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\t\tfloat hard_shadow = step( mean, shadowCoord.z );\n\t\t\t\t#else\n\t\t\t\t\tfloat hard_shadow = step( shadowCoord.z, mean );\n\t\t\t\t#endif\n\t\t\t\t\n\t\t\t\tif ( hard_shadow == 1.0 ) {\n\t\t\t\t\tshadow = 1.0;\n\t\t\t\t} else {\n\t\t\t\t\tvariance = max( variance, 0.0000001 );\n\t\t\t\t\tfloat d = shadowCoord.z - mean;\n\t\t\t\t\tfloat p_max = variance / ( variance + d * d );\n\t\t\t\t\tp_max = clamp( ( p_max - 0.3 ) / 0.65, 0.0, 1.0 );\n\t\t\t\t\tshadow = max( hard_shadow, p_max );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#else\n\t\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tshadowCoord.z -= shadowBias;\n\t\t\t#else\n\t\t\t\tshadowCoord.z += shadowBias;\n\t\t\t#endif\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tfloat depth = texture2D( shadowMap, shadowCoord.xy ).r;\n\t\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\t\tshadow = step( depth, shadowCoord.z );\n\t\t\t\t#else\n\t\t\t\t\tshadow = step( shadowCoord.z, depth );\n\t\t\t\t#endif\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#endif\n\t#if NUM_SUN_LIGHT_SHADOWS > 0\n\t\tfloat getSunShadow(\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\t\tsampler2DShadow shadowMap,\n\t\t\t#else\n\t\t\t\tsampler2D shadowMap,\n\t\t\t#endif\n\t\t\tSunLightShadow sunLightShadow,\n\t\t\tint shadowIndex\n\t\t) {\n\t\t\tvec4 shadowWorldPosition = vec4( vSunShadowWorldPosition.xyz + vSunShadowWorldNormal * sunLightShadow.shadowNormalBias, 1.0 );\n\t\t\tfloat viewDepth = vSunShadowWorldPosition.w;\n\t\t\tint cascadeOffset = shadowIndex * SUN_LIGHT_CASCADES;\n\t\t\tfloat shadow = 1.0;\n\t\t\tfor ( int i = SUN_LIGHT_CASCADES - 1; i >= 0; i -- ) {\n\t\t\t\tvec4 cascade = sunShadowCascade[ cascadeOffset + i ];\n\t\t\t\tif ( viewDepth >= cascade.x && viewDepth < cascade.y ) {\n\t\t\t\t\tfloat cascadeShadow = getShadow(\n\t\t\t\t\t\tshadowMap,\n\t\t\t\t\t\tsunLightShadow.shadowMapSize,\n\t\t\t\t\t\tsunLightShadow.shadowIntensity,\n\t\t\t\t\t\tsunLightShadow.shadowBias,\n\t\t\t\t\t\tsunLightShadow.shadowRadius,\n\t\t\t\t\t\tsunShadowMatrix[ cascadeOffset + i ] * shadowWorldPosition\n\t\t\t\t\t);\n\t\t\t\t\tshadow = mix( cascadeShadow, shadow, smoothstep( cascade.z, cascade.y, viewDepth ) );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn shadow;\n\t\t}\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\tfloat getPointShadow( samplerCubeShadow shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\tvec3 absVec = abs( lightToPosition );\n\t\tfloat viewSpaceZ = max( max( absVec.x, absVec.y ), absVec.z );\n\t\tif ( viewSpaceZ - shadowCameraFar <= 0.0 && viewSpaceZ - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat lightDistance = length( lightToPosition );\n\t\t\tfloat depthRange = shadowCameraFar - shadowCameraNear;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tfloat depthA = - shadowCameraNear / depthRange - shadowBias;\n\t\t\t\tfloat depthB = shadowCameraNear * shadowCameraFar / ( depthRange * lightDistance );\n\t\t\t#else\n\t\t\t\tfloat depthA = shadowCameraFar / depthRange + shadowBias;\n\t\t\t\tfloat depthB = - shadowCameraNear * shadowCameraFar / ( depthRange * lightDistance );\n\t\t\t#endif\n\t\t\tfloat texelSize = shadowRadius / shadowMapSize.x;\n\t\t\tvec3 absDir = abs( bd3D );\n\t\t\tvec3 tangent = absDir.x > absDir.z ? vec3( 0.0, 1.0, 0.0 ) : vec3( 1.0, 0.0, 0.0 );\n\t\t\ttangent = normalize( cross( bd3D, tangent ) );\n\t\t\tvec3 bitangent = cross( bd3D, tangent );\n\t\t\tfloat phi = interleavedGradientNoise( gl_FragCoord.xy ) * PI2;\n\t\t\tshadow = 0.0;\n\t\t\tfor ( int i = 0; i < 5; i ++ ) {\n\t\t\t\tvec2 offset = vogelDiskSample( i, 5, phi );\n\t\t\t\tvec3 direction = bd3D + ( tangent * offset.x + bitangent * offset.y ) * texelSize;\n\t\t\t\tvec3 absDirection = abs( direction );\n\t\t\t\tfloat dp = depthA + depthB / max( max( absDirection.x, absDirection.y ), absDirection.z );\n\t\t\t\tshadow += texture( shadowMap, vec4( direction, dp ) );\n\t\t\t}\n\t\t\tshadow *= 0.2;\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\t#elif defined( SHADOWMAP_TYPE_BASIC )\n\tfloat getPointShadow( samplerCube shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tvec3 absVec = abs( lightToPosition );\n\t\tfloat viewSpaceZ = max( max( absVec.x, absVec.y ), absVec.z );\n\t\tif ( viewSpaceZ - shadowCameraFar <= 0.0 && viewSpaceZ - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( shadowCameraFar * ( viewSpaceZ - shadowCameraNear ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );\n\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tfloat depth = textureCube( shadowMap, bd3D ).r;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tdepth = 1.0 - depth;\n\t\t\t#endif\n\t\t\tshadow = step( dp, depth );\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\t#endif\n\t#endif\n#endif";
478
476
 
479
477
  var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_SUN_LIGHT_SHADOWS > 0\n\t\tvarying vec4 vSunShadowWorldPosition;\n\t\tvarying vec3 vSunShadowWorldNormal;\n\t#endif\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif";
480
478
 
@@ -502,11 +500,11 @@ var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission =
502
500
 
503
501
  var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec4 transmittedLight;\n\t\tvec3 transmittance;\n\t\t#ifdef USE_DISPERSION\n\t\t\tfloat halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;\n\t\t\tvec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );\n\t\t\tfor ( int i = 0; i < 3; i ++ ) {\n\t\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );\n\t\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\t\trefractionCoords += 1.0;\n\t\t\t\trefractionCoords /= 2.0;\n\t\t\t\tvec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );\n\t\t\t\ttransmittedLight[ i ] = transmissionSample[ i ];\n\t\t\t\ttransmittedLight.a += transmissionSample.a;\n\t\t\t\ttransmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];\n\t\t\t}\n\t\t\ttransmittedLight.a /= 3.0;\n\t\t#else\n\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\trefractionCoords += 1.0;\n\t\t\trefractionCoords /= 2.0;\n\t\t\ttransmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\t\ttransmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\t#endif\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif";
504
502
 
505
- var uv_pars_fragment = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif";
503
+ var uv_pars_fragment = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_DIFFUSE_ROUGHNESSMAP\n\tvarying vec2 vDiffuseRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif";
506
504
 
507
- var uv_pars_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif";
505
+ var uv_pars_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_DIFFUSE_ROUGHNESSMAP\n\tuniform mat3 diffuseRoughnessMapTransform;\n\tvarying vec2 vDiffuseRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif";
508
506
 
509
- var uv_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif";
507
+ var uv_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DIFFUSE_ROUGHNESSMAP\n\tvDiffuseRoughnessMapUv = ( diffuseRoughnessMapTransform * vec3( DIFFUSE_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif";
510
508
 
511
509
  var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif";
512
510
 
@@ -516,7 +514,7 @@ const fragment$h = "uniform sampler2D t2D;\nuniform float backgroundIntensity;\n
516
514
 
517
515
  const vertex$g = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}";
518
516
 
519
- const fragment$g = "#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vWorldDirection );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n}";
517
+ const fragment$g = "uniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include <envmap_common_pars_fragment>\nvoid main() {\n\t#ifdef ENVMAP_TYPE_PMREM\n\t\tvec4 texColor = textureLod( envMap, backgroundRotation * vWorldDirection, roughnessToMip( backgroundBlurriness ) );\n\t#else\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vWorldDirection );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n}";
520
518
 
521
519
  const vertex$f = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}";
522
520
 
@@ -544,7 +542,7 @@ const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_
544
542
 
545
543
  const vertex$9 = "#define LAMBERT\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphinstance_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
546
544
 
547
- const fragment$9 = "#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_lambert_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_lambert_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
545
+ const fragment$9 = "#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_lambert_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_lambert_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
548
546
 
549
547
  const vertex$8 = "#define MATCAP\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <color_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphinstance_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\tvViewPosition = - mvPosition.xyz;\n}";
550
548
 
@@ -556,11 +554,11 @@ const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SH
556
554
 
557
555
  const vertex$6 = "#define PHONG\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphinstance_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
558
556
 
559
- const fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_phong_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
557
+ const fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_phong_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
560
558
 
561
559
  const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphinstance_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}";
562
560
 
563
- const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\n#endif\n#ifdef USE_RETROREFLECTION\n\tuniform float retroreflectivity;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <iridescence_fragment>\n#include <cube_uv_reflection_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_physical_pars_fragment>\n#include <transmission_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <clearcoat_pars_fragment>\n#include <iridescence_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <roughnessmap_fragment>\n\t#include <metalnessmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <clearcoat_normal_fragment_begin>\n\t#include <clearcoat_normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_physical_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include <transmission_fragment>\n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n \n\t\toutgoingLight = outgoingLight + sheenSpecularDirect + sheenSpecularIndirect;\n \n \t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
561
+ const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DIFFUSE_ROUGHNESS\n\tuniform float diffuseRoughness;\n\t#ifdef USE_DIFFUSE_ROUGHNESSMAP\n\t\tuniform sampler2D diffuseRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\n#endif\n#ifdef USE_RETROREFLECTION\n\tuniform float retroreflectivity;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <iridescence_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_physical_pars_fragment>\n#include <transmission_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <clearcoat_pars_fragment>\n#include <iridescence_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <roughnessmap_fragment>\n\t#include <metalnessmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <clearcoat_normal_fragment_begin>\n\t#include <clearcoat_normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_physical_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include <transmission_fragment>\n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n \n\t\toutgoingLight = outgoingLight + sheenSpecularDirect + sheenSpecularIndirect;\n \n \t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
564
562
 
565
563
  const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphinstance_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
566
564
 
@@ -603,7 +601,6 @@ const ShaderChunk = {
603
601
  color_pars_vertex: color_pars_vertex,
604
602
  color_vertex: color_vertex,
605
603
  common: common,
606
- cube_uv_reflection_fragment: cube_uv_reflection_fragment,
607
604
  defaultnormal_vertex: defaultnormal_vertex,
608
605
  displacementmap_pars_vertex: displacementmap_pars_vertex,
609
606
  displacementmap_vertex: displacementmap_vertex,
@@ -931,10 +928,10 @@ const UniformsLib = {
931
928
  ltc_1: { value: null },
932
929
  ltc_2: { value: null },
933
930
 
934
- probesSH: { value: null },
935
- probesMin: { value: /*@__PURE__*/ new Vector3() },
936
- probesMax: { value: /*@__PURE__*/ new Vector3() },
937
- probesResolution: { value: /*@__PURE__*/ new Vector3() }
931
+ probesSH: { value: [] },
932
+ probesMin: { value: [] },
933
+ probesMax: { value: [] },
934
+ probesResolution: { value: [] }
938
935
 
939
936
  },
940
937
 
@@ -1277,6 +1274,9 @@ ShaderLib.physical = {
1277
1274
  clearcoatRoughness: { value: 0 },
1278
1275
  clearcoatRoughnessMap: { value: null },
1279
1276
  clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() },
1277
+ diffuseRoughness: { value: 0 },
1278
+ diffuseRoughnessMap: { value: null },
1279
+ diffuseRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() },
1280
1280
  dispersion: { value: 0 },
1281
1281
  retroreflectivity: { value: 0 },
1282
1282
  iridescence: { value: 0 },
@@ -1400,7 +1400,7 @@ function WebGLBackground( renderer, environments, state, objects, alpha, premult
1400
1400
 
1401
1401
  const background = getBackground( scene );
1402
1402
 
1403
- if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) {
1403
+ if ( background && background.isCubeTexture ) {
1404
1404
 
1405
1405
  if ( boxMesh === undefined ) {
1406
1406
 
@@ -1452,7 +1452,7 @@ function WebGLBackground( renderer, environments, state, objects, alpha, premult
1452
1452
  // note: since the matrix is orthonormal, we can use the more-efficient transpose() in lieu of invert()
1453
1453
  boxMesh.material.uniforms.backgroundRotation.value.setFromMatrix4( _m1$1.makeRotationFromEuler( scene.backgroundRotation ) ).transpose();
1454
1454
 
1455
- if ( background.isCubeTexture && background.isRenderTargetTexture === false ) {
1455
+ if ( background.isRenderTargetTexture === false ) {
1456
1456
 
1457
1457
  boxMesh.material.uniforms.backgroundRotation.value.premultiply( _m$1 );
1458
1458
 
@@ -1968,11 +1968,13 @@ function WebGLBindingStates( gl, attributes ) {
1968
1968
 
1969
1969
  if ( geometryAttribute.isInterleavedBufferAttribute ) {
1970
1970
 
1971
+ // interleaved attributes can also view a buffer attribute, e.g. the columns of instance matrices
1972
+
1971
1973
  const data = geometryAttribute.data;
1972
- const stride = data.stride;
1974
+ const stride = data.isInterleavedBuffer === true ? data.stride : data.itemSize;
1973
1975
  const offset = geometryAttribute.offset;
1974
1976
 
1975
- if ( data.isInstancedInterleavedBuffer ) {
1977
+ if ( data.isInstancedInterleavedBuffer || data.isInstancedBufferAttribute ) {
1976
1978
 
1977
1979
  for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
1978
1980
 
@@ -2418,8 +2420,8 @@ function WebGLCapabilities( gl, extensions, parameters, utils ) {
2418
2420
 
2419
2421
  }
2420
2422
 
2421
- const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
2422
2423
  const reversedDepthBuffer = parameters.reversedDepthBuffer === true && extensions.has( 'EXT_clip_control' );
2424
+ const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true && reversedDepthBuffer === false;
2423
2425
 
2424
2426
  if ( parameters.reversedDepthBuffer === true && reversedDepthBuffer === false ) {
2425
2427
 
@@ -2427,6 +2429,12 @@ function WebGLCapabilities( gl, extensions, parameters, utils ) {
2427
2429
 
2428
2430
  }
2429
2431
 
2432
+ if ( parameters.logarithmicDepthBuffer === true && reversedDepthBuffer === true ) {
2433
+
2434
+ warn( 'WebGLRenderer: Logarithmic depth buffer is ignored when reversed depth buffer is enabled.' );
2435
+
2436
+ }
2437
+
2430
2438
  const maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
2431
2439
  const maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
2432
2440
  const maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE );
@@ -2638,44 +2646,209 @@ function WebGLClipping( properties ) {
2638
2646
 
2639
2647
  }
2640
2648
 
2641
- const LOD_MIN = 4;
2649
+ /**
2650
+ * A cube render target used in context of {@link WebGLRenderer}.
2651
+ *
2652
+ * @augments WebGLRenderTarget
2653
+ */
2654
+ class WebGLCubeRenderTarget extends WebGLRenderTarget {
2655
+
2656
+ /**
2657
+ * Constructs a new cube render target.
2658
+ *
2659
+ * @param {number} [size=1] - The size of the render target.
2660
+ * @param {RenderTarget~Options} [options] - The configuration object.
2661
+ */
2662
+ constructor( size = 1, options = {} ) {
2663
+
2664
+ super( size, size, options );
2642
2665
 
2643
- // The number of extra mips.
2644
- // Used for scene blur in fromScene() method.
2645
- const EXTRA_LODS = 6;
2666
+ /**
2667
+ * This flag can be used for type testing.
2668
+ *
2669
+ * @type {boolean}
2670
+ * @readonly
2671
+ * @default true
2672
+ */
2673
+ this.isWebGLCubeRenderTarget = true;
2674
+
2675
+ const image = { width: size, height: size, depth: 1 };
2676
+ const images = [ image, image, image, image, image, image ];
2677
+
2678
+ /**
2679
+ * Overwritten with a different texture type.
2680
+ *
2681
+ * @type {DataArrayTexture}
2682
+ */
2683
+ this.texture = new CubeTexture( images );
2684
+ this._setTextureOptions( options );
2685
+
2686
+ // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
2687
+ // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
2688
+ // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
2689
+
2690
+ // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
2691
+ // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture
2692
+ // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures).
2693
+
2694
+ this.texture.isRenderTargetTexture = true;
2695
+
2696
+ }
2697
+
2698
+ /**
2699
+ * Converts the given equirectangular texture to a cube map.
2700
+ *
2701
+ * @param {WebGLRenderer} renderer - The renderer.
2702
+ * @param {Texture} texture - The equirectangular texture.
2703
+ * @return {WebGLCubeRenderTarget} A reference to this cube render target.
2704
+ */
2705
+ fromEquirectangularTexture( renderer, texture ) {
2706
+
2707
+ this.texture.type = texture.type;
2708
+ this.texture.colorSpace = texture.colorSpace;
2709
+
2710
+ this.texture.generateMipmaps = texture.generateMipmaps;
2711
+ this.texture.minFilter = texture.minFilter;
2712
+ this.texture.magFilter = texture.magFilter;
2713
+
2714
+ const shader = {
2715
+
2716
+ uniforms: {
2717
+ tEquirect: { value: null },
2718
+ },
2719
+
2720
+ vertexShader: /* glsl */`
2721
+
2722
+ varying vec3 vWorldDirection;
2723
+
2724
+ vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
2725
+
2726
+ return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
2727
+
2728
+ }
2729
+
2730
+ void main() {
2731
+
2732
+ vWorldDirection = transformDirection( position, modelMatrix );
2733
+
2734
+ #include <begin_vertex>
2735
+ #include <project_vertex>
2736
+
2737
+ }
2738
+ `,
2739
+
2740
+ fragmentShader: /* glsl */`
2741
+
2742
+ uniform sampler2D tEquirect;
2743
+
2744
+ varying vec3 vWorldDirection;
2745
+
2746
+ #include <common>
2747
+
2748
+ void main() {
2749
+
2750
+ vec3 direction = normalize( vWorldDirection );
2751
+
2752
+ vec2 sampleUV = equirectUv( direction );
2753
+
2754
+ gl_FragColor = texture2D( tEquirect, sampleUV );
2755
+
2756
+ }
2757
+ `
2758
+ };
2759
+
2760
+ const geometry = new BoxGeometry( 5, 5, 5 );
2646
2761
 
2647
- // The number of spiral samples per blur pass.
2648
- // Used for scene blur in fromScene() method.
2762
+ const material = new ShaderMaterial( {
2763
+
2764
+ name: 'CubemapFromEquirect',
2765
+
2766
+ uniforms: cloneUniforms( shader.uniforms ),
2767
+ vertexShader: shader.vertexShader,
2768
+ fragmentShader: shader.fragmentShader,
2769
+ side: BackSide,
2770
+ blending: NoBlending
2771
+
2772
+ } );
2773
+
2774
+ material.uniforms.tEquirect.value = texture;
2775
+
2776
+ const mesh = new Mesh( geometry, material );
2777
+
2778
+ const currentMinFilter = texture.minFilter;
2779
+
2780
+ // Avoid blurred poles
2781
+ if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter;
2782
+
2783
+ const camera = new CubeCamera( 1, 10, this );
2784
+ camera.update( renderer, mesh );
2785
+
2786
+ texture.minFilter = currentMinFilter;
2787
+
2788
+ mesh.geometry.dispose();
2789
+ mesh.material.dispose();
2790
+
2791
+ return this;
2792
+
2793
+ }
2794
+
2795
+ /**
2796
+ * Clears this cube render target.
2797
+ *
2798
+ * @param {WebGLRenderer} renderer - The renderer.
2799
+ * @param {boolean} [color=true] - Whether the color buffer should be cleared or not.
2800
+ * @param {boolean} [depth=true] - Whether the depth buffer should be cleared or not.
2801
+ * @param {boolean} [stencil=true] - Whether the stencil buffer should be cleared or not.
2802
+ */
2803
+ clear( renderer, color = true, depth = true, stencil = true ) {
2804
+
2805
+ const currentRenderTarget = renderer.getRenderTarget();
2806
+
2807
+ for ( let i = 0; i < 6; i ++ ) {
2808
+
2809
+ renderer.setRenderTarget( this, i );
2810
+
2811
+ renderer.clear( color, depth, stencil );
2812
+
2813
+ }
2814
+
2815
+ renderer.setRenderTarget( currentRenderTarget );
2816
+
2817
+ }
2818
+
2819
+ }
2820
+
2821
+ // Smaller inputs are upsampled so that every PMREM has enough mip levels.
2822
+ const MIN_SIZE = 256;
2823
+
2824
+ // Log2 of the face size of the roughest mip level. Smaller faces can't
2825
+ // represent the diffuse irradiance that is stored in this level.
2826
+ const LOD_MIN = 3;
2827
+
2828
+ // Spiral samples per pass of the initial fromScene() blur.
2649
2829
  const BLUR_SAMPLES = 20;
2650
2830
 
2651
- // GGX VNDF importance sampling configuration
2831
+ // GGX VNDF samples for the sharp mip levels.
2652
2832
  const GGX_SAMPLES = 256;
2653
2833
 
2654
- const _flatCamera = /*@__PURE__*/ new OrthographicCamera();
2655
- const _clearColor = /*@__PURE__*/ new Color();
2656
- let _oldTarget = null;
2657
- let _oldActiveCubeFace = 0;
2658
- let _oldActiveMipmapLevel = 0;
2659
- let _oldXrEnabled = false;
2834
+ // Integrate a small source mip for the rough levels to avoid sampling noise.
2835
+ const INTEGRATION_SIZE = 16;
2836
+ const INTEGRATION_LEVELS = 3;
2660
2837
 
2661
2838
  const _origin = /*@__PURE__*/ new Vector3();
2662
- const _direction = /*@__PURE__*/ new Vector3();
2839
+ const _clearColor = /*@__PURE__*/ new Color();
2663
2840
 
2664
2841
  /**
2665
- * This class generates a Prefiltered, Mipmapped Radiance Environment Map
2666
- * (PMREM) from a cubeMap environment texture. This allows different levels of
2667
- * blur to be quickly accessed based on material roughness. It is packed into a
2668
- * special CubeUV format that allows us to perform custom interpolation so that
2669
- * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap
2670
- * chain, it only goes down to the LOD_MIN level (above), and then creates extra
2671
- * even more filtered 'mips' at the same LOD_MIN resolution, associated with
2672
- * higher roughness levels. In this way we maintain resolution to smoothly
2673
- * interpolate diffuse lighting while limiting sampling computation.
2842
+ * Generates a Prefiltered, Mipmapped Radiance Environment Map (PMREM) for
2843
+ * image-based lighting. The result is a cube render target whose mip levels
2844
+ * store GGX-filtered radiance at increasing roughness, from a mirror at level 0
2845
+ * to roughness 1. See {@link PMREMGenerator.lodToRoughness} for the mapping.
2846
+ *
2847
+ * Filtering assumes the view direction equals the surface normal. Sharp levels
2848
+ * use GGX visible normal sampling (Heitz, 2018), while rough levels integrate a
2849
+ * lower-resolution source cubemap.
2674
2850
  *
2675
- * The prefiltering uses GGX VNDF (Visible Normal Distribution Function)
2676
- * importance sampling based on "Sampling the GGX Distribution of Visible Normals"
2677
- * (Heitz, 2018) to generate environment maps that accurately match the GGX BRDF
2678
- * used in material rendering for physically-based image-based lighting.
2851
+ * @see {@link https://jcgt.org/published/0007/04/01/ | Sampling the GGX Distribution of Visible Normals}
2679
2852
  */
2680
2853
  class PMREMGenerator {
2681
2854
 
@@ -2687,37 +2860,34 @@ class PMREMGenerator {
2687
2860
  constructor( renderer ) {
2688
2861
 
2689
2862
  this._renderer = renderer;
2690
- this._pingPongRenderTarget = null;
2691
2863
 
2692
- this._lodMax = 0;
2693
2864
  this._cubeSize = 0;
2694
- this._sizeLods = [];
2695
- this._lodMeshes = [];
2865
+ this._sourceTarget = null;
2696
2866
 
2697
- this._backgroundBox = null;
2867
+ this._cubeCamera = new CubeCamera( 1, 10, null );
2868
+ this._boxMesh = new Mesh( new BoxGeometry( 5, 5, 5 ), null );
2698
2869
 
2699
2870
  this._cubemapMaterial = null;
2700
2871
  this._equirectMaterial = null;
2701
2872
 
2702
2873
  this._blurMaterial = null;
2703
2874
  this._ggxMaterial = null;
2875
+ this._integrationMaterial = null;
2704
2876
 
2705
2877
  }
2706
2878
 
2707
2879
  /**
2708
- * Generates a PMREM from a supplied Scene, which can be faster than using an
2709
- * image if networking bandwidth is low. Optional sigma specifies a blur radius
2710
- * in radians to be applied to the scene before PMREM generation. Optional near
2711
- * and far planes ensure the scene is rendered in its entirety.
2880
+ * Generates a PMREM from a scene, optionally applying a Gaussian blur before
2881
+ * GGX filtering.
2712
2882
  *
2713
2883
  * @param {Scene} scene - The scene to be captured.
2714
2884
  * @param {number} [sigma=0] - The blur radius in radians.
2715
2885
  * @param {number} [near=0.1] - The near plane distance.
2716
2886
  * @param {number} [far=100] - The far plane distance.
2717
2887
  * @param {Object} [options={}] - The configuration options.
2718
- * @param {number} [options.size=256] - The texture size of the PMREM.
2888
+ * @param {number} [options.size=256] - The texture size of the PMREM, rounded down to a power of two and at least 256.
2719
2889
  * @param {Vector3} [options.position=origin] - The position of the internal cube camera that renders the scene.
2720
- * @return {WebGLRenderTarget} The resulting PMREM.
2890
+ * @return {WebGLCubeRenderTarget} The resulting PMREM.
2721
2891
  */
2722
2892
  fromScene( scene, sigma = 0, near = 0.1, far = 100, options = {} ) {
2723
2893
 
@@ -2726,42 +2896,66 @@ class PMREMGenerator {
2726
2896
  position = _origin,
2727
2897
  } = options;
2728
2898
 
2729
- _oldTarget = this._renderer.getRenderTarget();
2730
- _oldActiveCubeFace = this._renderer.getActiveCubeFace();
2731
- _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel();
2732
- _oldXrEnabled = this._renderer.xr.enabled;
2733
-
2734
- this._renderer.xr.enabled = false;
2899
+ const renderer = this._renderer;
2735
2900
 
2736
2901
  this._setSize( size );
2737
2902
 
2738
- const cubeUVRenderTarget = this._allocateTargets();
2739
- cubeUVRenderTarget.depthBuffer = true;
2903
+ const pmremTarget = this._allocateTarget();
2904
+ const sourceTarget = this._getSourceTarget( true );
2740
2905
 
2741
- this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget, position );
2906
+ if ( sigma > 0 ) {
2907
+
2908
+ sourceTarget.texture.mipmapsAutoUpdate = false;
2909
+
2910
+ }
2911
+
2912
+ // Clear every captured face, independent of the application's clear settings.
2913
+
2914
+ const autoClear = renderer.autoClear;
2915
+ const autoClearColor = renderer.autoClearColor;
2916
+ const autoClearDepth = renderer.autoClearDepth;
2917
+ const autoClearStencil = renderer.autoClearStencil;
2918
+ const background = scene.background;
2919
+
2920
+ renderer.autoClear = true;
2921
+ renderer.autoClearColor = true;
2922
+ renderer.autoClearDepth = true;
2923
+ renderer.autoClearStencil = true;
2924
+
2925
+ if ( background === null ) scene.background = renderer.getClearColor( _clearColor );
2926
+
2927
+ const cubeCamera = new CubeCamera( near, far, sourceTarget );
2928
+ cubeCamera.position.copy( position );
2929
+ cubeCamera.update( renderer, scene );
2930
+
2931
+ renderer.autoClear = autoClear;
2932
+ renderer.autoClearColor = autoClearColor;
2933
+ renderer.autoClearDepth = autoClearDepth;
2934
+ renderer.autoClearStencil = autoClearStencil;
2935
+
2936
+ scene.background = background;
2742
2937
 
2743
2938
  if ( sigma > 0 ) {
2744
2939
 
2745
- this._blur( cubeUVRenderTarget, 0, 0, sigma );
2940
+ sourceTarget.texture.mipmapsAutoUpdate = true;
2941
+ this._blur( pmremTarget, sigma );
2746
2942
 
2747
2943
  }
2748
2944
 
2749
- this._applyPMREM( cubeUVRenderTarget );
2750
- this._cleanup( cubeUVRenderTarget );
2945
+ this._applyPMREM( pmremTarget );
2751
2946
 
2752
- return cubeUVRenderTarget;
2947
+ return pmremTarget;
2753
2948
 
2754
2949
  }
2755
2950
 
2756
2951
  /**
2757
- * Generates a PMREM from an equirectangular texture, which can be either LDR
2758
- * or HDR. The ideal input image size is 1k (1024 x 512), as this matches best
2759
- * with the 256 x 256 cubemap output. The minimum supported input image size
2760
- * is 64 x 32.
2952
+ * Generates a PMREM from an LDR or HDR equirectangular texture. The cube face
2953
+ * size is one quarter of the image width, rounded down to a power of two and
2954
+ * at least 256.
2761
2955
  *
2762
2956
  * @param {Texture} equirectangular - The equirectangular texture to be converted.
2763
- * @param {?WebGLRenderTarget} [renderTarget=null] - The render target to use.
2764
- * @return {WebGLRenderTarget} The resulting PMREM.
2957
+ * @param {?WebGLCubeRenderTarget} [renderTarget=null] - The render target to use.
2958
+ * @return {WebGLCubeRenderTarget} The resulting PMREM.
2765
2959
  */
2766
2960
  fromEquirectangular( equirectangular, renderTarget = null ) {
2767
2961
 
@@ -2770,14 +2964,12 @@ class PMREMGenerator {
2770
2964
  }
2771
2965
 
2772
2966
  /**
2773
- * Generates a PMREM from an cubemap texture, which can be either LDR
2774
- * or HDR. The ideal input cube size is 256 x 256, as this matches best
2775
- * with the 256 x 256 cubemap output. The minimum supported input cube
2776
- * size is 16 x 16 per face.
2967
+ * Generates a PMREM from an LDR or HDR cubemap. The cube face size matches
2968
+ * the input, rounded down to a power of two and at least 256.
2777
2969
  *
2778
2970
  * @param {Texture} cubemap - The cubemap texture to be converted.
2779
- * @param {?WebGLRenderTarget} [renderTarget=null] - The render target to use.
2780
- * @return {WebGLRenderTarget} The resulting PMREM.
2971
+ * @param {?WebGLCubeRenderTarget} [renderTarget=null] - The render target to use.
2972
+ * @return {WebGLCubeRenderTarget} The resulting PMREM.
2781
2973
  */
2782
2974
  fromCubemap( cubemap, renderTarget = null ) {
2783
2975
 
@@ -2816,57 +3008,42 @@ class PMREMGenerator {
2816
3008
  }
2817
3009
 
2818
3010
  /**
2819
- * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
2820
- * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
2821
- * one of them will cause any others to also become unusable.
3011
+ * Disposes of the PMREMGenerator's internal memory. The PMREMs it returned
3012
+ * belong to the caller and are not disposed.
2822
3013
  */
2823
3014
  dispose() {
2824
3015
 
2825
- this._dispose();
3016
+ if ( this._sourceTarget !== null ) this._sourceTarget.dispose();
2826
3017
 
2827
3018
  if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose();
2828
3019
  if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose();
2829
-
2830
- if ( this._backgroundBox !== null ) {
2831
-
2832
- this._backgroundBox.geometry.dispose();
2833
- this._backgroundBox.material.dispose();
2834
-
2835
- }
2836
-
2837
- }
2838
-
2839
- // private interface
2840
-
2841
- _setSize( cubeSize ) {
2842
-
2843
- this._lodMax = Math.floor( Math.log2( cubeSize ) );
2844
- this._cubeSize = Math.pow( 2, this._lodMax );
2845
-
2846
- }
2847
-
2848
- _dispose() {
2849
-
2850
3020
  if ( this._blurMaterial !== null ) this._blurMaterial.dispose();
2851
3021
  if ( this._ggxMaterial !== null ) this._ggxMaterial.dispose();
3022
+ if ( this._integrationMaterial !== null ) this._integrationMaterial.dispose();
2852
3023
 
2853
- if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose();
3024
+ this._boxMesh.geometry.dispose();
2854
3025
 
2855
- for ( let i = 0; i < this._lodMeshes.length; i ++ ) {
3026
+ }
2856
3027
 
2857
- this._lodMeshes[ i ].geometry.dispose();
3028
+ /**
3029
+ * Returns the roughness a mip level of a PMREM has been prefiltered for.
3030
+ * The inverse mapping is used by the renderers when sampling a PMREM.
3031
+ *
3032
+ * @param {number} lod - The mip level.
3033
+ * @param {number} maxLod - The last mip level of the PMREM.
3034
+ * @return {number} The roughness.
3035
+ */
3036
+ static lodToRoughness( lod, maxLod ) {
2858
3037
 
2859
- }
3038
+ return maxLod > 0 ? 1 - Math.sqrt( 1 - lod / maxLod ) : 0;
2860
3039
 
2861
3040
  }
2862
3041
 
2863
- _cleanup( outputTarget ) {
3042
+ // private interface
2864
3043
 
2865
- this._renderer.setRenderTarget( _oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel );
2866
- this._renderer.xr.enabled = _oldXrEnabled;
3044
+ _setSize( cubeSize ) {
2867
3045
 
2868
- outputTarget.scissorTest = false;
2869
- _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height );
3046
+ this._cubeSize = Math.max( MIN_SIZE, floorPowerOfTwo( cubeSize ) );
2870
3047
 
2871
3048
  }
2872
3049
 
@@ -2874,7 +3051,7 @@ class PMREMGenerator {
2874
3051
 
2875
3052
  if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) {
2876
3053
 
2877
- this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) );
3054
+ this._setSize( texture.image.length === 0 ? MIN_SIZE : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) );
2878
3055
 
2879
3056
  } else { // Equirectangular
2880
3057
 
@@ -2882,187 +3059,97 @@ class PMREMGenerator {
2882
3059
 
2883
3060
  }
2884
3061
 
2885
- _oldTarget = this._renderer.getRenderTarget();
2886
- _oldActiveCubeFace = this._renderer.getActiveCubeFace();
2887
- _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel();
2888
- _oldXrEnabled = this._renderer.xr.enabled;
2889
-
2890
- this._renderer.xr.enabled = false;
3062
+ const pmremTarget = renderTarget || this._allocateTarget();
2891
3063
 
2892
- const cubeUVRenderTarget = renderTarget || this._allocateTargets();
2893
- this._textureToCubeUV( texture, cubeUVRenderTarget );
2894
- this._applyPMREM( cubeUVRenderTarget );
2895
- this._cleanup( cubeUVRenderTarget );
3064
+ this._textureToCubemap( texture );
3065
+ this._applyPMREM( pmremTarget );
2896
3066
 
2897
- return cubeUVRenderTarget;
3067
+ return pmremTarget;
2898
3068
 
2899
3069
  }
2900
3070
 
2901
- _allocateTargets() {
2902
-
2903
- const width = 3 * Math.max( this._cubeSize, 16 * 7 );
2904
- const height = 4 * this._cubeSize;
2905
-
2906
- const params = {
2907
- magFilter: LinearFilter,
2908
- minFilter: LinearFilter,
2909
- generateMipmaps: false,
2910
- type: HalfFloatType,
2911
- format: RGBAFormat,
2912
- colorSpace: LinearSRGBColorSpace,
2913
- depthBuffer: false
2914
- };
2915
-
2916
- const cubeUVRenderTarget = _createRenderTarget( width, height, params );
2917
-
2918
- if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height ) {
3071
+ _allocateTarget() {
2919
3072
 
2920
- if ( this._pingPongRenderTarget !== null ) {
3073
+ const size = this._cubeSize;
2921
3074
 
2922
- this._dispose();
3075
+ const pmremTarget = _createRenderTarget( size, false, false );
2923
3076
 
2924
- }
3077
+ // Allocate only the prefiltered mip levels without automatic mipmap generation.
2925
3078
 
2926
- this._pingPongRenderTarget = _createRenderTarget( width, height, params );
3079
+ const maxLod = Math.log2( size ) - LOD_MIN;
2927
3080
 
2928
- const { _lodMax } = this;
2929
- ( { lodMeshes: this._lodMeshes, sizeLods: this._sizeLods } = _createPlanes( _lodMax ) );
3081
+ for ( let lod = 0; lod <= maxLod; lod ++ ) {
2930
3082
 
2931
- this._blurMaterial = _getBlurShader( _lodMax, width, height );
2932
- this._ggxMaterial = _getGGXShader( _lodMax, width, height );
3083
+ pmremTarget.texture.mipmaps.push( { width: size >> lod, height: size >> lod } );
2933
3084
 
2934
3085
  }
2935
3086
 
2936
- return cubeUVRenderTarget;
3087
+ pmremTarget.texture.name = 'PMREM';
3088
+ pmremTarget.texture.isPMREMTexture = true;
2937
3089
 
2938
- }
2939
-
2940
- _compileMaterial( material ) {
2941
-
2942
- const mesh = new Mesh( new BufferGeometry(), material );
2943
- this._renderer.compile( mesh, _flatCamera );
3090
+ return pmremTarget;
2944
3091
 
2945
3092
  }
2946
3093
 
2947
- _sceneToCubeUV( scene, near, far, cubeUVRenderTarget, position ) {
2948
-
2949
- const fov = 90;
2950
- const aspect = 1;
2951
- const cubeCamera = new PerspectiveCamera( fov, aspect, near, far );
2952
- const upSign = [ 1, -1, 1, 1, 1, 1 ];
2953
- const forwardSign = [ 1, 1, 1, -1, -1, -1 ];
2954
- const renderer = this._renderer;
2955
-
2956
- const originalAutoClear = renderer.autoClear;
2957
- const toneMapping = renderer.toneMapping;
2958
- renderer.getClearColor( _clearColor );
2959
-
2960
- renderer.toneMapping = NoToneMapping;
2961
- renderer.autoClear = false;
2962
-
2963
- // https://github.com/mrdoob/three.js/issues/31413#issuecomment-3095966812
2964
- const reversedDepthBuffer = renderer.state.buffers.depth.getReversed();
2965
-
2966
- if ( reversedDepthBuffer ) {
2967
-
2968
- renderer.setRenderTarget( cubeUVRenderTarget );
2969
- renderer.clearDepth();
2970
- renderer.setRenderTarget( null );
2971
-
2972
- }
2973
-
2974
- if ( this._backgroundBox === null ) {
2975
-
2976
- this._backgroundBox = new Mesh(
2977
- new BoxGeometry(),
2978
- new MeshBasicMaterial( {
2979
- name: 'PMREM.Background',
2980
- side: BackSide,
2981
- depthWrite: false,
2982
- depthTest: false,
2983
- } )
2984
- );
2985
-
2986
- }
2987
-
2988
- const backgroundBox = this._backgroundBox;
2989
- const backgroundMaterial = backgroundBox.material;
3094
+ _getSourceTarget( depthBuffer = false ) {
2990
3095
 
2991
- let useSolidColor = false;
2992
-
2993
- const background = scene.background;
2994
-
2995
- if ( background ) {
2996
-
2997
- if ( background.isColor ) {
2998
-
2999
- backgroundMaterial.color.copy( background );
3000
- scene.background = null;
3001
- useSolidColor = true;
3096
+ const size = this._cubeSize;
3097
+ const sourceTarget = this._sourceTarget;
3002
3098
 
3003
- }
3099
+ if ( sourceTarget === null || sourceTarget.width !== size || ( depthBuffer && sourceTarget.depthBuffer === false ) ) {
3004
3100
 
3005
- } else {
3101
+ if ( sourceTarget !== null ) sourceTarget.dispose();
3006
3102
 
3007
- backgroundMaterial.color.copy( _clearColor );
3008
- useSolidColor = true;
3103
+ this._sourceTarget = _createRenderTarget( size, true, depthBuffer );
3009
3104
 
3010
3105
  }
3011
3106
 
3012
- for ( let i = 0; i < 6; i ++ ) {
3013
-
3014
- const col = i % 3;
3015
-
3016
- if ( col === 0 ) {
3017
-
3018
- cubeCamera.up.set( 0, upSign[ i ], 0 );
3019
- cubeCamera.position.set( position.x, position.y, position.z );
3020
- cubeCamera.lookAt( position.x + forwardSign[ i ], position.y, position.z );
3021
-
3022
- } else if ( col === 1 ) {
3023
-
3024
- cubeCamera.up.set( 0, 0, upSign[ i ] );
3025
- cubeCamera.position.set( position.x, position.y, position.z );
3026
- cubeCamera.lookAt( position.x, position.y + forwardSign[ i ], position.z );
3107
+ return this._sourceTarget;
3027
3108
 
3109
+ }
3028
3110
 
3029
- } else {
3111
+ _compileMaterial( material ) {
3030
3112
 
3031
- cubeCamera.up.set( 0, upSign[ i ], 0 );
3032
- cubeCamera.position.set( position.x, position.y, position.z );
3033
- cubeCamera.lookAt( position.x, position.y, position.z + forwardSign[ i ] );
3113
+ this._boxMesh.material = material;
3114
+ this._renderer.compile( this._boxMesh, this._cubeCamera.children[ 0 ] );
3034
3115
 
3035
- }
3116
+ }
3036
3117
 
3037
- const size = this._cubeSize;
3118
+ /**
3119
+ * Renders the box mesh with the given material into all six faces of a cube render target.
3120
+ *
3121
+ * @private
3122
+ * @param {WebGLCubeRenderTarget} target - The render target.
3123
+ * @param {number} lod - The mip level to render into.
3124
+ * @param {ShaderMaterial} material - The material.
3125
+ */
3126
+ _renderCube( target, lod, material ) {
3038
3127
 
3039
- _setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size );
3128
+ const boxMesh = this._boxMesh;
3129
+ const cubeCamera = this._cubeCamera;
3040
3130
 
3041
- renderer.setRenderTarget( cubeUVRenderTarget );
3131
+ boxMesh.material = material;
3042
3132
 
3043
- if ( useSolidColor ) {
3133
+ cubeCamera.renderTarget = target;
3134
+ cubeCamera.activeMipmapLevel = lod;
3044
3135
 
3045
- renderer.render( backgroundBox, cubeCamera );
3136
+ // WebGLRenderer uses the target viewport without scaling it to the active mip.
3046
3137
 
3047
- }
3138
+ const size = target.width >> lod;
3048
3139
 
3049
- renderer.render( scene, cubeCamera );
3140
+ target.viewport.set( 0, 0, size, size );
3050
3141
 
3051
- }
3142
+ cubeCamera.update( this._renderer, boxMesh );
3052
3143
 
3053
- renderer.toneMapping = toneMapping;
3054
- renderer.autoClear = originalAutoClear;
3055
- scene.background = background;
3144
+ target.viewport.set( 0, 0, target.width, target.height );
3056
3145
 
3057
3146
  }
3058
3147
 
3059
- _textureToCubeUV( texture, cubeUVRenderTarget ) {
3148
+ _textureToCubemap( texture ) {
3060
3149
 
3061
- const renderer = this._renderer;
3150
+ let material;
3062
3151
 
3063
- const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping );
3064
-
3065
- if ( isCubeTexture ) {
3152
+ if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) {
3066
3153
 
3067
3154
  if ( this._cubemapMaterial === null ) {
3068
3155
 
@@ -3070,7 +3157,8 @@ class PMREMGenerator {
3070
3157
 
3071
3158
  }
3072
3159
 
3073
- this._cubemapMaterial.uniforms.flipEnvMap.value = ( texture.isRenderTargetTexture === false ) ? -1 : 1;
3160
+ material = this._cubemapMaterial;
3161
+ material.uniforms.flipEnvMap.value = ( texture.isRenderTargetTexture === false ) ? -1 : 1;
3074
3162
 
3075
3163
  } else {
3076
3164
 
@@ -3080,770 +3168,402 @@ class PMREMGenerator {
3080
3168
 
3081
3169
  }
3082
3170
 
3083
- }
3084
-
3085
- const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial;
3086
-
3087
- const mesh = this._lodMeshes[ 0 ];
3088
- mesh.material = material;
3089
-
3090
- const uniforms = material.uniforms;
3091
-
3092
- uniforms[ 'envMap' ].value = texture;
3093
-
3094
- const size = this._cubeSize;
3095
-
3096
- _setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size );
3097
-
3098
- renderer.setRenderTarget( cubeUVRenderTarget );
3099
- renderer.render( mesh, _flatCamera );
3100
-
3101
- }
3102
-
3103
- _applyPMREM( cubeUVRenderTarget ) {
3104
-
3105
- const renderer = this._renderer;
3106
- const autoClear = renderer.autoClear;
3107
- renderer.autoClear = false;
3108
-
3109
- const n = this._lodMeshes.length;
3110
-
3111
- // Use GGX VNDF importance sampling
3112
- for ( let i = 1; i < n; i ++ ) {
3113
-
3114
- this._applyGGXFilter( cubeUVRenderTarget, i - 1, i );
3171
+ material = this._equirectMaterial;
3115
3172
 
3116
3173
  }
3117
3174
 
3118
- renderer.autoClear = autoClear;
3119
-
3120
- }
3121
-
3122
- /**
3123
- * Applies GGX VNDF importance sampling filter to generate a prefiltered environment map.
3124
- * Uses Monte Carlo integration with VNDF importance sampling to accurately represent the
3125
- * GGX BRDF for physically-based rendering. Reads from the previous LOD level and
3126
- * applies incremental roughness filtering to avoid over-blurring.
3127
- *
3128
- * @private
3129
- * @param {WebGLRenderTarget} cubeUVRenderTarget
3130
- * @param {number} lodIn - Source LOD level to read from
3131
- * @param {number} lodOut - Target LOD level to write to
3132
- */
3133
- _applyGGXFilter( cubeUVRenderTarget, lodIn, lodOut ) {
3134
-
3135
- const renderer = this._renderer;
3136
- const pingPongRenderTarget = this._pingPongRenderTarget;
3137
-
3138
- const ggxMaterial = this._ggxMaterial;
3139
- const ggxMesh = this._lodMeshes[ lodOut ];
3140
- ggxMesh.material = ggxMaterial;
3175
+ material.uniforms.envMap.value = texture;
3141
3176
 
3142
- const ggxUniforms = ggxMaterial.uniforms;
3143
-
3144
- // Calculate incremental roughness between LOD levels
3145
- const targetRoughness = lodOut / ( this._lodMeshes.length - 1 );
3146
- const sourceRoughness = lodIn / ( this._lodMeshes.length - 1 );
3147
- const incrementalRoughness = Math.sqrt( targetRoughness * targetRoughness - sourceRoughness * sourceRoughness );
3148
-
3149
- // Apply blur strength mapping for better quality across the roughness range
3150
- const blurStrength = targetRoughness * 1.25;
3151
- const adjustedRoughness = incrementalRoughness * blurStrength;
3152
-
3153
- // Calculate viewport position based on output LOD level
3154
- const { _lodMax } = this;
3155
- const outputSize = this._sizeLods[ lodOut ];
3156
- const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 );
3157
- const y = 4 * ( this._cubeSize - outputSize );
3158
-
3159
- // Read from previous LOD with incremental roughness
3160
- ggxUniforms[ 'envMap' ].value = cubeUVRenderTarget.texture;
3161
- ggxUniforms[ 'roughness' ].value = adjustedRoughness;
3162
- ggxUniforms[ 'mipInt' ].value = _lodMax - lodIn; // Sample from input LOD
3163
-
3164
- _setViewport( pingPongRenderTarget, x, y, 3 * outputSize, 2 * outputSize );
3165
- renderer.setRenderTarget( pingPongRenderTarget );
3166
- renderer.render( ggxMesh, _flatCamera );
3167
-
3168
- // Copy from pingPong back to cubeUV (simple direct copy)
3169
- ggxUniforms[ 'envMap' ].value = pingPongRenderTarget.texture;
3170
- ggxUniforms[ 'roughness' ].value = 0.0; // Direct copy
3171
- ggxUniforms[ 'mipInt' ].value = _lodMax - lodOut; // Read from the level we just wrote
3172
-
3173
- _setViewport( cubeUVRenderTarget, x, y, 3 * outputSize, 2 * outputSize );
3174
- renderer.setRenderTarget( cubeUVRenderTarget );
3175
- renderer.render( ggxMesh, _flatCamera );
3177
+ this._renderCube( this._getSourceTarget(), 0, material );
3176
3178
 
3177
3179
  }
3178
3180
 
3179
3181
  /**
3180
- * This is a two-pass Gaussian blur for a cubemap. Each pass importance-samples
3181
- * the Gaussian along a spiral kernel (Golden Angle), which distributes samples
3182
- * isotropically on the sphere (no pole artifacts).
3183
- *
3184
- * Used for initial scene blur in fromScene() method when sigma > 0.
3182
+ * Prefilters the source cubemap into the mip levels of the PMREM. The sharp levels
3183
+ * integrate the GGX lobe of their roughness with VNDF importance sampling, reading the
3184
+ * mip level of the source that matches the solid angle of each sample. The rough
3185
+ * levels weight every texel of a small source mip with the GGX lobe instead.
3185
3186
  *
3186
3187
  * @private
3187
- * @param {WebGLRenderTarget} cubeUVRenderTarget
3188
- * @param {number} lodIn
3189
- * @param {number} lodOut
3190
- * @param {number} sigma
3188
+ * @param {WebGLCubeRenderTarget} pmremTarget - The PMREM.
3191
3189
  */
3192
- _blur( cubeUVRenderTarget, lodIn, lodOut, sigma ) {
3193
-
3194
- const pingPongRenderTarget = this._pingPongRenderTarget;
3195
-
3196
- // Two passes of sigma / sqrt( 2 ) compose to a blur of sigma while squaring
3197
- // the effective sample count. Sigmas beyond PI are visually indistinguishable
3198
- // from a uniform blur, so clamp to keep the shader math finite.
3199
- const blurSigma = Math.min( sigma, Math.PI ) / Math.SQRT2;
3200
-
3201
- this._blurPass( cubeUVRenderTarget, pingPongRenderTarget, lodIn, lodOut, blurSigma );
3202
- this._blurPass( pingPongRenderTarget, cubeUVRenderTarget, lodOut, lodOut, blurSigma );
3203
-
3204
- }
3205
-
3206
- _blurPass( targetIn, targetOut, lodIn, lodOut, sigmaRadians ) {
3190
+ _applyPMREM( pmremTarget ) {
3207
3191
 
3208
- const renderer = this._renderer;
3209
- const blurMaterial = this._blurMaterial;
3210
-
3211
- const blurMesh = this._lodMeshes[ lodOut ];
3212
- blurMesh.material = blurMaterial;
3213
-
3214
- const blurUniforms = blurMaterial.uniforms;
3215
-
3216
- blurUniforms[ 'envMap' ].value = targetIn.texture;
3217
- blurUniforms[ 'sigma' ].value = sigmaRadians;
3218
- blurUniforms[ 'mipInt' ].value = this._lodMax - lodIn;
3219
-
3220
- const outputSize = this._sizeLods[ lodOut ];
3221
- const x = 3 * outputSize * ( lodOut > this._lodMax - LOD_MIN ? lodOut - this._lodMax + LOD_MIN : 0 );
3222
- const y = 4 * ( this._cubeSize - outputSize );
3223
-
3224
- _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize );
3225
- renderer.setRenderTarget( targetOut );
3226
- renderer.render( blurMesh, _flatCamera );
3227
-
3228
- }
3229
-
3230
- }
3231
-
3232
-
3233
-
3234
- function _createPlanes( lodMax ) {
3235
-
3236
- const sizeLods = [];
3237
- const lodMeshes = [];
3238
-
3239
- let lod = lodMax;
3192
+ if ( this._ggxMaterial === null ) {
3240
3193
 
3241
- const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LODS;
3194
+ this._ggxMaterial = _getGGXMaterial();
3195
+ this._integrationMaterial = _getIntegrationMaterial();
3242
3196
 
3243
- for ( let i = 0; i < totalLods; i ++ ) {
3244
-
3245
- const sizeLod = Math.pow( 2, lod );
3246
- sizeLods.push( sizeLod );
3247
-
3248
- // UVs overshoot the face by one texel to bake the CubeUV border into the directions.
3249
- const texelSize = 1.0 / ( sizeLod - 2 );
3250
- const min = - texelSize;
3251
- const max = 1 + texelSize;
3252
- const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ];
3253
-
3254
- const cubeFaces = 6;
3255
- const vertices = 6;
3256
- const positionSize = 3;
3257
-
3258
- const position = new Float32Array( positionSize * vertices * cubeFaces );
3259
- const outputDirection = new Float32Array( positionSize * vertices * cubeFaces );
3260
-
3261
- for ( let face = 0; face < cubeFaces; face ++ ) {
3262
-
3263
- const x = ( face % 3 ) * 2 / 3 - 1;
3264
- const y = face > 2 ? 0 : -1;
3265
- const coordinates = [
3266
- x, y, 0,
3267
- x + 2 / 3, y, 0,
3268
- x + 2 / 3, y + 1, 0,
3269
- x, y, 0,
3270
- x + 2 / 3, y + 1, 0,
3271
- x, y + 1, 0
3272
- ];
3273
- position.set( coordinates, positionSize * vertices * face );
3274
-
3275
- for ( let vertex = 0; vertex < vertices; vertex ++ ) {
3276
-
3277
- const u = uv1[ vertex * 2 ] * 2 - 1;
3278
- const v = uv1[ vertex * 2 + 1 ] * 2 - 1;
3279
-
3280
- // RH coordinate system; PMREM face-indexing convention
3281
- if ( face === 0 ) {
3197
+ }
3282
3198
 
3283
- _direction.set( 1, v, u ); // pos x
3199
+ const size = this._cubeSize;
3200
+ const maxLod = pmremTarget.texture.mipmaps.length - 1;
3284
3201
 
3285
- } else if ( face === 1 ) {
3202
+ const ggxUniforms = this._ggxMaterial.uniforms;
3203
+ ggxUniforms.envMap.value = this._sourceTarget.texture;
3286
3204
 
3287
- _direction.set( - u, 1, - v ); // pos y
3205
+ const integrationUniforms = this._integrationMaterial.uniforms;
3206
+ integrationUniforms.envMap.value = this._sourceTarget.texture;
3207
+ integrationUniforms.sourceLod.value = Math.log2( size / INTEGRATION_SIZE );
3288
3208
 
3289
- } else if ( face === 2 ) {
3209
+ for ( let lod = 0; lod <= maxLod; lod ++ ) {
3290
3210
 
3291
- _direction.set( - u, v, 1 ); // pos z
3211
+ const roughness = PMREMGenerator.lodToRoughness( lod, maxLod );
3292
3212
 
3293
- } else if ( face === 3 ) {
3213
+ if ( lod > maxLod - INTEGRATION_LEVELS ) {
3294
3214
 
3295
- _direction.set( -1, v, - u ); // neg x
3215
+ integrationUniforms.roughness.value = roughness;
3296
3216
 
3297
- } else if ( face === 4 ) {
3217
+ this._renderCube( pmremTarget, lod, this._integrationMaterial );
3298
3218
 
3299
- _direction.set( - u, -1, v ); // neg y
3219
+ } else {
3300
3220
 
3301
- } else {
3221
+ // For V = N, pdf( L ) = D( H ) / 4. Match the source texel solid angle to
3222
+ // 1 / ( GGX_SAMPLES * pdf ), with a half-mip bias to reduce sampling noise.
3223
+ // The shader supplies log2 of the GGX denominator.
3224
+ const lodBias = roughness > 0 ? Math.log2( size ) + 0.5 * Math.log2( 6 / ( GGX_SAMPLES * Math.pow( roughness, 4 ) ) ) + 0.5 : 0;
3302
3225
 
3303
- _direction.set( u, v, -1 ); // neg z
3226
+ ggxUniforms.roughness.value = roughness;
3227
+ ggxUniforms.lodBias.value = lodBias;
3304
3228
 
3305
- }
3306
-
3307
- _direction.toArray( outputDirection, ( face * vertices + vertex ) * positionSize );
3229
+ this._renderCube( pmremTarget, lod, this._ggxMaterial );
3308
3230
 
3309
3231
  }
3310
3232
 
3311
3233
  }
3312
3234
 
3313
- const planes = new BufferGeometry();
3314
- planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) );
3315
- planes.setAttribute( 'outputDirection', new BufferAttribute( outputDirection, positionSize ) );
3316
- lodMeshes.push( new Mesh( planes, null ) );
3317
-
3318
- if ( lod > LOD_MIN ) {
3319
-
3320
- lod --;
3321
-
3322
- }
3323
-
3324
3235
  }
3325
3236
 
3326
- return { lodMeshes, sizeLods };
3327
-
3328
- }
3329
-
3330
- function _createRenderTarget( width, height, params ) {
3331
-
3332
- const cubeUVRenderTarget = new WebGLRenderTarget( width, height, params );
3333
- cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
3334
- cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
3335
- cubeUVRenderTarget.scissorTest = true;
3336
- return cubeUVRenderTarget;
3337
-
3338
- }
3339
-
3340
- function _setViewport( target, x, y, width, height ) {
3341
-
3342
- target.viewport.set( x, y, width, height );
3343
- target.scissor.set( x, y, width, height );
3344
-
3345
- }
3346
-
3347
- function _getGGXShader( lodMax, width, height ) {
3348
-
3349
- const shaderMaterial = new ShaderMaterial( {
3350
-
3351
- name: 'PMREMGGXConvolution',
3352
-
3353
- defines: {
3354
- 'GGX_SAMPLES': GGX_SAMPLES,
3355
- 'CUBEUV_TEXEL_WIDTH': 1.0 / width,
3356
- 'CUBEUV_TEXEL_HEIGHT': 1.0 / height,
3357
- 'CUBEUV_MAX_MIP': `${lodMax}.0`,
3358
- },
3359
-
3360
- uniforms: {
3361
- 'envMap': { value: null },
3362
- 'roughness': { value: 0.0 },
3363
- 'mipInt': { value: 0 }
3364
- },
3365
-
3366
- vertexShader: _getCommonVertexShader(),
3367
-
3368
- fragmentShader: /* glsl */`
3369
-
3370
- precision highp float;
3371
- precision highp int;
3372
-
3373
- varying vec3 vOutputDirection;
3374
-
3375
- uniform sampler2D envMap;
3376
- uniform float roughness;
3377
- uniform float mipInt;
3378
-
3379
- #define ENVMAP_TYPE_CUBE_UV
3380
- #include <cube_uv_reflection_fragment>
3381
-
3382
- #define PI 3.14159265359
3383
-
3384
- // Van der Corput radical inverse
3385
- float radicalInverse_VdC(uint bits) {
3386
- bits = (bits << 16u) | (bits >> 16u);
3387
- bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
3388
- bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
3389
- bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
3390
- bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
3391
- return float(bits) * 2.3283064365386963e-10; // / 0x100000000
3392
- }
3393
-
3394
- // Hammersley sequence
3395
- vec2 hammersley(uint i, uint N) {
3396
- return vec2(float(i) / float(N), radicalInverse_VdC(i));
3397
- }
3398
-
3399
- // GGX VNDF importance sampling (Eric Heitz 2018)
3400
- // "Sampling the GGX Distribution of Visible Normals"
3401
- // https://jcgt.org/published/0007/04/01/
3402
- vec3 importanceSampleGGX_VNDF(vec2 Xi, vec3 V, float roughness) {
3403
- float alpha = roughness * roughness;
3404
-
3405
- // Section 4.1: Orthonormal basis
3406
- vec3 T1 = vec3(1.0, 0.0, 0.0);
3407
- vec3 T2 = cross(V, T1);
3408
-
3409
- // Section 4.2: Parameterization of projected area
3410
- float r = sqrt(Xi.x);
3411
- float phi = 2.0 * PI * Xi.y;
3412
- float t1 = r * cos(phi);
3413
- float t2 = r * sin(phi);
3414
- float s = 0.5 * (1.0 + V.z);
3415
- t2 = (1.0 - s) * sqrt(1.0 - t1 * t1) + s * t2;
3416
-
3417
- // Section 4.3: Reprojection onto hemisphere
3418
- vec3 Nh = t1 * T1 + t2 * T2 + sqrt(max(0.0, 1.0 - t1 * t1 - t2 * t2)) * V;
3419
-
3420
- // Section 3.4: Transform back to ellipsoid configuration
3421
- return normalize(vec3(alpha * Nh.x, alpha * Nh.y, max(0.0, Nh.z)));
3422
- }
3423
-
3424
- void main() {
3425
- vec3 N = normalize(vOutputDirection);
3426
- vec3 V = N; // Assume view direction equals normal for pre-filtering
3427
-
3428
- vec3 prefilteredColor = vec3(0.0);
3429
- float totalWeight = 0.0;
3237
+ /**
3238
+ * Applies the initial fromScene() blur in two passes using a golden-angle
3239
+ * spiral kernel. Level 0 of the PMREM serves as the intermediate target.
3240
+ *
3241
+ * @private
3242
+ * @param {WebGLCubeRenderTarget} pmremTarget - The PMREM.
3243
+ * @param {number} sigma - The blur radius in radians.
3244
+ */
3245
+ _blur( pmremTarget, sigma ) {
3430
3246
 
3431
- // For very low roughness, just sample the environment directly
3432
- if (roughness < 0.001) {
3433
- gl_FragColor = vec4(bilinearCubeUV(envMap, N, mipInt), 1.0);
3434
- return;
3435
- }
3247
+ if ( this._blurMaterial === null ) {
3436
3248
 
3437
- // Tangent space basis for VNDF sampling
3438
- vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
3439
- vec3 tangent = normalize(cross(up, N));
3440
- vec3 bitangent = cross(N, tangent);
3249
+ this._blurMaterial = _getBlurMaterial();
3441
3250
 
3442
- for(uint i = 0u; i < uint(GGX_SAMPLES); i++) {
3443
- vec2 Xi = hammersley(i, uint(GGX_SAMPLES));
3251
+ }
3444
3252
 
3445
- // For PMREM, V = N, so in tangent space V is always (0, 0, 1)
3446
- vec3 H_tangent = importanceSampleGGX_VNDF(Xi, vec3(0.0, 0.0, 1.0), roughness);
3253
+ const material = this._blurMaterial;
3254
+ const uniforms = material.uniforms;
3447
3255
 
3448
- // Transform H back to world space
3449
- vec3 H = normalize(tangent * H_tangent.x + bitangent * H_tangent.y + N * H_tangent.z);
3450
- vec3 L = normalize(2.0 * dot(V, H) * H - V);
3256
+ const sourceTarget = this._sourceTarget;
3451
3257
 
3452
- float NdotL = max(dot(N, L), 0.0);
3258
+ // Split the blur variance between two passes. Clamp sigma to the sphere's
3259
+ // maximum angular distance.
3260
+ uniforms.sigma.value = Math.min( sigma, Math.PI ) / Math.SQRT2;
3453
3261
 
3454
- if(NdotL > 0.0) {
3455
- // Sample environment at fixed mip level
3456
- // VNDF importance sampling handles the distribution filtering
3457
- vec3 sampleColor = bilinearCubeUV(envMap, L, mipInt);
3262
+ uniforms.envMap.value = sourceTarget.texture;
3263
+ this._renderCube( pmremTarget, 0, material );
3458
3264
 
3459
- // Weight by NdotL for the split-sum approximation
3460
- // VNDF PDF naturally accounts for the visible microfacet distribution
3461
- prefilteredColor += sampleColor * NdotL;
3462
- totalWeight += NdotL;
3463
- }
3464
- }
3265
+ uniforms.envMap.value = pmremTarget.texture;
3266
+ this._renderCube( sourceTarget, 0, material );
3465
3267
 
3466
- if (totalWeight > 0.0) {
3467
- prefilteredColor = prefilteredColor / totalWeight;
3468
- }
3268
+ }
3469
3269
 
3470
- gl_FragColor = vec4(prefilteredColor, 1.0);
3471
- }
3472
- `,
3270
+ }
3473
3271
 
3474
- blending: NoBlending,
3475
- depthTest: false,
3476
- depthWrite: false
3272
+ function _createRenderTarget( size, generateMipmaps, depthBuffer ) {
3477
3273
 
3274
+ return new WebGLCubeRenderTarget( size, {
3275
+ minFilter: LinearMipmapLinearFilter,
3276
+ generateMipmaps: generateMipmaps,
3277
+ type: HalfFloatType,
3278
+ colorSpace: LinearSRGBColorSpace,
3279
+ depthBuffer: depthBuffer
3478
3280
  } );
3479
3281
 
3480
- return shaderMaterial;
3481
-
3482
3282
  }
3483
3283
 
3484
- function _getBlurShader( lodMax, width, height ) {
3485
-
3486
- const shaderMaterial = new ShaderMaterial( {
3487
-
3488
- name: 'SphericalGaussianBlur',
3489
-
3490
- defines: {
3491
- 'SAMPLES': BLUR_SAMPLES,
3492
- 'CUBEUV_TEXEL_WIDTH': 1.0 / width,
3493
- 'CUBEUV_TEXEL_HEIGHT': 1.0 / height,
3494
- 'CUBEUV_MAX_MIP': `${lodMax}.0`,
3495
- },
3496
-
3497
- uniforms: {
3498
- 'envMap': { value: null },
3499
- 'sigma': { value: 0 },
3500
- 'mipInt': { value: 0 },
3501
- },
3502
-
3503
- vertexShader: _getCommonVertexShader(),
3504
-
3505
- fragmentShader: /* glsl */`
3506
-
3507
- precision highp float;
3508
- precision highp int;
3509
-
3510
- varying vec3 vOutputDirection;
3511
-
3512
- uniform sampler2D envMap;
3513
- uniform float sigma;
3514
- uniform float mipInt;
3515
-
3516
- #define ENVMAP_TYPE_CUBE_UV
3517
- #include <cube_uv_reflection_fragment>
3518
-
3519
- #define PI 3.14159265359
3520
- #define GOLDEN_ANGLE 2.39996322973
3521
-
3522
- void main() {
3523
-
3524
- if ( sigma == 0.0 ) {
3525
-
3526
- gl_FragColor = vec4( bilinearCubeUV( envMap, vOutputDirection, mipInt ), 1.0 );
3527
- return;
3528
-
3529
- }
3530
-
3531
- vec3 outputDirection = normalize( vOutputDirection );
3532
-
3533
- vec3 up = abs( outputDirection.z ) < 0.999 ? vec3( 0.0, 0.0, 1.0 ) : vec3( 1.0, 0.0, 0.0 );
3534
- vec3 tangent = normalize( cross( up, outputDirection ) );
3535
- vec3 bitangent = cross( outputDirection, tangent );
3536
-
3537
- // Truncate the kernel at three standard deviations or at the antipode.
3538
- float thetaMax = min( 3.0 * sigma, PI );
3539
- float truncation = 1.0 - exp( - 0.5 * thetaMax * thetaMax / ( sigma * sigma ) );
3540
-
3541
- vec3 accumColor = vec3( 0.0 );
3542
- float accumWeight = 0.0;
3543
-
3544
- for ( int i = 0; i < SAMPLES; i ++ ) {
3545
-
3546
- // Stratified inverse-CDF sampling of the Gaussian, placed on a golden-angle spiral.
3547
- float stratum = ( float( i ) + 0.5 ) / float( SAMPLES );
3548
- float theta = sigma * sqrt( - 2.0 * log( 1.0 - stratum * truncation ) );
3549
- float phi = float( i ) * GOLDEN_ANGLE;
3284
+ function _getMaterial( name, uniforms, fragmentShader ) {
3550
3285
 
3551
- vec3 offset = cos( phi ) * tangent + sin( phi ) * bitangent;
3552
- vec3 sampleDirection = cos( theta ) * outputDirection + sin( theta ) * offset;
3553
-
3554
- // Correct the planar sample density to solid angle.
3555
- float weight = sin( theta ) / theta;
3556
-
3557
- accumColor += weight * bilinearCubeUV( envMap, sampleDirection, mipInt );
3558
- accumWeight += weight;
3286
+ return new ShaderMaterial( {
3559
3287
 
3560
- }
3288
+ name: name,
3561
3289
 
3562
- gl_FragColor = vec4( accumColor / accumWeight, 1.0 );
3290
+ uniforms: uniforms,
3563
3291
 
3564
- }
3565
- `,
3292
+ vertexShader: ShaderChunk.cube_vert,
3293
+ fragmentShader: fragmentShader,
3566
3294
 
3295
+ side: BackSide,
3567
3296
  blending: NoBlending,
3568
3297
  depthTest: false,
3569
3298
  depthWrite: false
3570
3299
 
3571
3300
  } );
3572
3301
 
3573
- return shaderMaterial;
3574
-
3575
3302
  }
3576
3303
 
3577
- function _getEquirectMaterial() {
3304
+ function _getGGXMaterial() {
3578
3305
 
3579
- return new ShaderMaterial( {
3306
+ return _getMaterial( 'PMREMGGXConvolution', {
3307
+ 'envMap': { value: null },
3308
+ 'roughness': { value: 0 },
3309
+ 'lodBias': { value: 0 }
3310
+ }, /* glsl */`
3580
3311
 
3581
- name: 'EquirectangularToCubeUV',
3312
+ #define GGX_SAMPLES ${ GGX_SAMPLES }u
3582
3313
 
3583
- uniforms: {
3584
- 'envMap': { value: null }
3585
- },
3314
+ varying vec3 vWorldDirection;
3586
3315
 
3587
- vertexShader: _getCommonVertexShader(),
3316
+ uniform samplerCube envMap;
3317
+ uniform float roughness;
3318
+ uniform float lodBias;
3588
3319
 
3589
- fragmentShader: /* glsl */`
3590
-
3591
- precision mediump float;
3592
- precision mediump int;
3320
+ #include <common>
3593
3321
 
3594
- varying vec3 vOutputDirection;
3322
+ // Van der Corput radical inverse
3323
+ float radicalInverse_VdC( uint bits ) {
3595
3324
 
3596
- uniform sampler2D envMap;
3325
+ bits = ( bits << 16u ) | ( bits >> 16u );
3326
+ bits = ( ( bits & 0x55555555u ) << 1u ) | ( ( bits & 0xAAAAAAAAu ) >> 1u );
3327
+ bits = ( ( bits & 0x33333333u ) << 2u ) | ( ( bits & 0xCCCCCCCCu ) >> 2u );
3328
+ bits = ( ( bits & 0x0F0F0F0Fu ) << 4u ) | ( ( bits & 0xF0F0F0F0u ) >> 4u );
3329
+ bits = ( ( bits & 0x00FF00FFu ) << 8u ) | ( ( bits & 0xFF00FF00u ) >> 8u );
3330
+ return float( bits ) * 2.3283064365386963e-10; // / 0x100000000
3597
3331
 
3598
- #include <common>
3332
+ }
3599
3333
 
3600
- void main() {
3334
+ // Hammersley sequence
3335
+ vec2 hammersley( uint i, uint N ) {
3601
3336
 
3602
- vec3 outputDirection = normalize( vOutputDirection );
3603
- vec2 uv = equirectUv( outputDirection );
3337
+ return vec2( float( i ) / float( N ), radicalInverse_VdC( i ) );
3604
3338
 
3605
- gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );
3339
+ }
3606
3340
 
3607
- }
3608
- `,
3341
+ void main() {
3609
3342
 
3610
- blending: NoBlending,
3611
- depthTest: false,
3612
- depthWrite: false
3343
+ vec3 N = normalize( vWorldDirection );
3613
3344
 
3614
- } );
3345
+ // For very low roughness, just sample the environment directly
3346
+ if ( roughness < 0.001 ) {
3615
3347
 
3616
- }
3348
+ gl_FragColor = vec4( textureLod( envMap, N, 0.0 ).rgb, 1.0 );
3349
+ return;
3617
3350
 
3618
- function _getCubemapMaterial() {
3351
+ }
3619
3352
 
3620
- return new ShaderMaterial( {
3353
+ float alpha = roughness * roughness;
3354
+ float alpha2 = alpha * alpha;
3621
3355
 
3622
- name: 'CubemapToCubeUV',
3356
+ // Tangent space basis for VNDF sampling
3357
+ vec3 up = abs( N.z ) < 0.999 ? vec3( 0.0, 0.0, 1.0 ) : vec3( 1.0, 0.0, 0.0 );
3358
+ vec3 tangent = normalize( cross( up, N ) );
3359
+ vec3 bitangent = cross( N, tangent );
3623
3360
 
3624
- uniforms: {
3625
- 'envMap': { value: null },
3626
- 'flipEnvMap': { value: -1 }
3627
- },
3361
+ vec3 prefilteredColor = vec3( 0.0 );
3362
+ float totalWeight = 0.0;
3628
3363
 
3629
- vertexShader: _getCommonVertexShader(),
3364
+ for ( uint i = 0u; i < GGX_SAMPLES; i ++ ) {
3630
3365
 
3631
- fragmentShader: /* glsl */`
3366
+ vec2 Xi = hammersley( i, GGX_SAMPLES );
3632
3367
 
3633
- precision mediump float;
3634
- precision mediump int;
3368
+ // With V = N, sample the reflected direction directly.
3369
+ float invQ = 1.0 / ( 1.0 - Xi.x + alpha2 * Xi.x );
3370
+ float NdotL = ( 1.0 - Xi.x - alpha2 * Xi.x ) * invQ;
3635
3371
 
3636
- uniform float flipEnvMap;
3372
+ if ( NdotL > 0.0 ) {
3637
3373
 
3638
- varying vec3 vOutputDirection;
3374
+ float phi = 2.0 * PI * Xi.y;
3375
+ float sinTheta = 2.0 * alpha * sqrt( Xi.x * ( 1.0 - Xi.x ) ) * invQ;
3376
+ vec3 L = N * NdotL + ( tangent * cos( phi ) + bitangent * sin( phi ) ) * sinTheta;
3639
3377
 
3640
- uniform samplerCube envMap;
3378
+ // Match the source mip to the sample's solid angle. The terms
3379
+ // independent of the sample are precomputed in lodBias.
3380
+ float d = alpha2 * invQ;
3381
+ float lod = max( log2( d ) + lodBias, 0.0 );
3641
3382
 
3642
- void main() {
3383
+ // Weight by NdotL for the split-sum approximation
3384
+ prefilteredColor += textureLod( envMap, L, lod ).rgb * NdotL;
3385
+ totalWeight += NdotL;
3643
3386
 
3644
- gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );
3387
+ }
3645
3388
 
3646
3389
  }
3647
- `,
3648
3390
 
3649
- blending: NoBlending,
3650
- depthTest: false,
3651
- depthWrite: false
3391
+ gl_FragColor = vec4( prefilteredColor / totalWeight, 1.0 );
3652
3392
 
3653
- } );
3393
+ }
3394
+ ` );
3654
3395
 
3655
3396
  }
3656
3397
 
3657
- function _getCommonVertexShader() {
3398
+ function _getIntegrationMaterial() {
3658
3399
 
3659
- return /* glsl */`
3400
+ return _getMaterial( 'PMREMGGXIntegration', {
3401
+ 'envMap': { value: null },
3402
+ 'roughness': { value: 0 },
3403
+ 'sourceLod': { value: 0 },
3404
+ 'sourceSize': { value: INTEGRATION_SIZE } // a uniform so the loops aren't unrolled
3405
+ }, /* glsl */`
3660
3406
 
3661
- precision mediump float;
3662
- precision mediump int;
3407
+ varying vec3 vWorldDirection;
3663
3408
 
3664
- attribute vec3 outputDirection;
3665
-
3666
- varying vec3 vOutputDirection;
3409
+ uniform samplerCube envMap;
3410
+ uniform float roughness;
3411
+ uniform float sourceLod;
3412
+ uniform int sourceSize;
3667
3413
 
3668
3414
  void main() {
3669
3415
 
3670
- vOutputDirection = outputDirection;
3671
- gl_Position = vec4( position, 1.0 );
3672
-
3673
- }
3674
- `;
3675
-
3676
- }
3416
+ vec3 N = normalize( vWorldDirection );
3677
3417
 
3678
- /**
3679
- * A cube render target used in context of {@link WebGLRenderer}.
3680
- *
3681
- * @augments WebGLRenderTarget
3682
- */
3683
- class WebGLCubeRenderTarget extends WebGLRenderTarget {
3418
+ float alpha = roughness * roughness;
3419
+ float alpha2 = alpha * alpha;
3684
3420
 
3685
- /**
3686
- * Constructs a new cube render target.
3687
- *
3688
- * @param {number} [size=1] - The size of the render target.
3689
- * @param {RenderTarget~Options} [options] - The configuration object.
3690
- */
3691
- constructor( size = 1, options = {} ) {
3421
+ float texelSize = 2.0 / float( sourceSize );
3692
3422
 
3693
- super( size, size, options );
3423
+ vec3 prefilteredColor = vec3( 0.0 );
3424
+ float totalWeight = 0.0;
3694
3425
 
3695
- /**
3696
- * This flag can be used for type testing.
3697
- *
3698
- * @type {boolean}
3699
- * @readonly
3700
- * @default true
3701
- */
3702
- this.isWebGLCubeRenderTarget = true;
3426
+ // Pair opposite texels: only the one in N's hemisphere contributes.
3427
+ for ( int face = 0; face < 3; face ++ ) {
3703
3428
 
3704
- const image = { width: size, height: size, depth: 1 };
3705
- const images = [ image, image, image, image, image, image ];
3429
+ for ( int y = 0; y < sourceSize; y ++ ) {
3706
3430
 
3707
- /**
3708
- * Overwritten with a different texture type.
3709
- *
3710
- * @type {DataArrayTexture}
3711
- */
3712
- this.texture = new CubeTexture( images );
3713
- this._setTextureOptions( options );
3431
+ for ( int x = 0; x < sourceSize; x ++ ) {
3714
3432
 
3715
- // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
3716
- // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
3717
- // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
3433
+ vec2 uv = ( vec2( x, y ) + 0.5 ) * texelSize - 1.0;
3434
+ vec3 texelDirection = face == 0 ? vec3( 1.0, uv ) : ( face == 1 ? vec3( uv.x, 1.0, uv.y ) : vec3( uv, 1.0 ) );
3718
3435
 
3719
- // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
3720
- // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture
3721
- // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures).
3436
+ float invDistance = inversesqrt( 1.0 + dot( uv, uv ) );
3437
+ float NdotL = dot( N, texelDirection );
3438
+ texelDirection *= NdotL < 0.0 ? - 1.0 : 1.0;
3439
+ NdotL = abs( NdotL ) * invDistance;
3722
3440
 
3723
- this.texture.isRenderTargetTexture = true;
3441
+ // With V = N, NdotH squared is ( 1 + NdotL ) / 2. Common factors
3442
+ // in the GGX distribution and texel solid angle cancel when normalized.
3443
+ float d = 1.0 + alpha2 + ( alpha2 - 1.0 ) * NdotL;
3444
+ float weight = NdotL * invDistance * invDistance * invDistance / ( d * d );
3724
3445
 
3725
- }
3446
+ prefilteredColor += textureLod( envMap, texelDirection, sourceLod ).rgb * weight;
3447
+ totalWeight += weight;
3726
3448
 
3727
- /**
3728
- * Converts the given equirectangular texture to a cube map.
3729
- *
3730
- * @param {WebGLRenderer} renderer - The renderer.
3731
- * @param {Texture} texture - The equirectangular texture.
3732
- * @return {WebGLCubeRenderTarget} A reference to this cube render target.
3733
- */
3734
- fromEquirectangularTexture( renderer, texture ) {
3449
+ }
3735
3450
 
3736
- this.texture.type = texture.type;
3737
- this.texture.colorSpace = texture.colorSpace;
3451
+ }
3738
3452
 
3739
- this.texture.generateMipmaps = texture.generateMipmaps;
3740
- this.texture.minFilter = texture.minFilter;
3741
- this.texture.magFilter = texture.magFilter;
3453
+ }
3742
3454
 
3743
- const shader = {
3455
+ gl_FragColor = vec4( prefilteredColor / totalWeight, 1.0 );
3744
3456
 
3745
- uniforms: {
3746
- tEquirect: { value: null },
3747
- },
3457
+ }
3458
+ ` );
3748
3459
 
3749
- vertexShader: /* glsl */`
3460
+ }
3750
3461
 
3751
- varying vec3 vWorldDirection;
3462
+ function _getBlurMaterial() {
3752
3463
 
3753
- vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
3464
+ return _getMaterial( 'PMREMSphericalGaussianBlur', {
3465
+ 'envMap': { value: null },
3466
+ 'sigma': { value: 0 }
3467
+ }, /* glsl */`
3754
3468
 
3755
- return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
3469
+ #define SAMPLES ${ BLUR_SAMPLES }
3470
+ #define GOLDEN_ANGLE 2.39996322973
3756
3471
 
3757
- }
3472
+ varying vec3 vWorldDirection;
3758
3473
 
3759
- void main() {
3474
+ uniform samplerCube envMap;
3475
+ uniform float sigma;
3760
3476
 
3761
- vWorldDirection = transformDirection( position, modelMatrix );
3477
+ #include <common>
3762
3478
 
3763
- #include <begin_vertex>
3764
- #include <project_vertex>
3479
+ void main() {
3765
3480
 
3766
- }
3767
- `,
3481
+ vec3 outputDirection = normalize( vWorldDirection );
3768
3482
 
3769
- fragmentShader: /* glsl */`
3483
+ vec3 up = abs( outputDirection.z ) < 0.999 ? vec3( 0.0, 0.0, 1.0 ) : vec3( 1.0, 0.0, 0.0 );
3484
+ vec3 tangent = normalize( cross( up, outputDirection ) );
3485
+ vec3 bitangent = cross( outputDirection, tangent );
3770
3486
 
3771
- uniform sampler2D tEquirect;
3487
+ // Truncate the kernel at three standard deviations or at the antipode.
3488
+ float thetaMax = min( 3.0 * sigma, PI );
3489
+ float truncation = 1.0 - exp( - 0.5 * thetaMax * thetaMax / ( sigma * sigma ) );
3772
3490
 
3773
- varying vec3 vWorldDirection;
3491
+ vec3 accumColor = vec3( 0.0 );
3492
+ float accumWeight = 0.0;
3774
3493
 
3775
- #include <common>
3494
+ for ( int i = 0; i < SAMPLES; i ++ ) {
3776
3495
 
3777
- void main() {
3496
+ // Stratified inverse-CDF sampling of the Gaussian, placed on a golden-angle spiral.
3497
+ float stratum = ( float( i ) + 0.5 ) / float( SAMPLES );
3498
+ float theta = sigma * sqrt( - 2.0 * log( 1.0 - stratum * truncation ) );
3499
+ float phi = float( i ) * GOLDEN_ANGLE;
3778
3500
 
3779
- vec3 direction = normalize( vWorldDirection );
3501
+ vec3 offset = cos( phi ) * tangent + sin( phi ) * bitangent;
3502
+ vec3 sampleDirection = cos( theta ) * outputDirection + sin( theta ) * offset;
3780
3503
 
3781
- vec2 sampleUV = equirectUv( direction );
3504
+ // Correct the planar sample density to solid angle.
3505
+ float weight = sin( theta ) / theta;
3782
3506
 
3783
- gl_FragColor = texture2D( tEquirect, sampleUV );
3507
+ accumColor += weight * textureLod( envMap, sampleDirection, 0.0 ).rgb;
3508
+ accumWeight += weight;
3784
3509
 
3785
- }
3786
- `
3787
- };
3510
+ }
3788
3511
 
3789
- const geometry = new BoxGeometry( 5, 5, 5 );
3512
+ gl_FragColor = vec4( accumColor / accumWeight, 1.0 );
3790
3513
 
3791
- const material = new ShaderMaterial( {
3514
+ }
3515
+ ` );
3792
3516
 
3793
- name: 'CubemapFromEquirect',
3517
+ }
3794
3518
 
3795
- uniforms: cloneUniforms( shader.uniforms ),
3796
- vertexShader: shader.vertexShader,
3797
- fragmentShader: shader.fragmentShader,
3798
- side: BackSide,
3799
- blending: NoBlending
3519
+ function _getEquirectMaterial() {
3800
3520
 
3801
- } );
3521
+ return _getMaterial( 'PMREMEquirectangularToCubemap', {
3522
+ 'envMap': { value: null }
3523
+ }, /* glsl */`
3802
3524
 
3803
- material.uniforms.tEquirect.value = texture;
3525
+ varying vec3 vWorldDirection;
3804
3526
 
3805
- const mesh = new Mesh( geometry, material );
3527
+ uniform sampler2D envMap;
3806
3528
 
3807
- const currentMinFilter = texture.minFilter;
3529
+ #include <common>
3808
3530
 
3809
- // Avoid blurred poles
3810
- if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter;
3531
+ void main() {
3811
3532
 
3812
- const camera = new CubeCamera( 1, 10, this );
3813
- camera.update( renderer, mesh );
3533
+ // Average four subpixel samples to preserve small, bright features.
3534
+ vec3 direction = normalize( vWorldDirection );
3535
+ vec3 dx = dFdx( direction ) * 0.25;
3536
+ vec3 dy = dFdy( direction ) * 0.25;
3814
3537
 
3815
- texture.minFilter = currentMinFilter;
3538
+ vec3 color = textureLod( envMap, equirectUv( normalize( direction - dx - dy ) ), 0.0 ).rgb;
3539
+ color += textureLod( envMap, equirectUv( normalize( direction + dx - dy ) ), 0.0 ).rgb;
3540
+ color += textureLod( envMap, equirectUv( normalize( direction - dx + dy ) ), 0.0 ).rgb;
3541
+ color += textureLod( envMap, equirectUv( normalize( direction + dx + dy ) ), 0.0 ).rgb;
3542
+ gl_FragColor = vec4( color * 0.25, 1.0 );
3816
3543
 
3817
- mesh.geometry.dispose();
3818
- mesh.material.dispose();
3544
+ }
3545
+ ` );
3819
3546
 
3820
- return this;
3547
+ }
3821
3548
 
3822
- }
3549
+ function _getCubemapMaterial() {
3823
3550
 
3824
- /**
3825
- * Clears this cube render target.
3826
- *
3827
- * @param {WebGLRenderer} renderer - The renderer.
3828
- * @param {boolean} [color=true] - Whether the color buffer should be cleared or not.
3829
- * @param {boolean} [depth=true] - Whether the depth buffer should be cleared or not.
3830
- * @param {boolean} [stencil=true] - Whether the stencil buffer should be cleared or not.
3831
- */
3832
- clear( renderer, color = true, depth = true, stencil = true ) {
3551
+ return _getMaterial( 'PMREMCubemapToCubemap', {
3552
+ 'envMap': { value: null },
3553
+ 'flipEnvMap': { value: -1 }
3554
+ }, /* glsl */`
3833
3555
 
3834
- const currentRenderTarget = renderer.getRenderTarget();
3556
+ varying vec3 vWorldDirection;
3835
3557
 
3836
- for ( let i = 0; i < 6; i ++ ) {
3558
+ uniform samplerCube envMap;
3559
+ uniform float flipEnvMap;
3837
3560
 
3838
- renderer.setRenderTarget( this, i );
3561
+ void main() {
3839
3562
 
3840
- renderer.clear( color, depth, stencil );
3563
+ gl_FragColor = vec4( textureCube( envMap, vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) ).rgb, 1.0 );
3841
3564
 
3842
3565
  }
3843
-
3844
- renderer.setRenderTarget( currentRenderTarget );
3845
-
3846
- }
3566
+ ` );
3847
3567
 
3848
3568
  }
3849
3569
 
@@ -3915,14 +3635,14 @@ function WebGLEnvironments( renderer ) {
3915
3635
 
3916
3636
  function getPMREM( texture ) {
3917
3637
 
3918
- if ( texture && texture.isTexture ) {
3638
+ if ( texture && texture.isTexture && texture.isPMREMTexture !== true ) {
3919
3639
 
3920
3640
  const mapping = texture.mapping;
3921
3641
 
3922
3642
  const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping );
3923
3643
  const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping );
3924
3644
 
3925
- // equirect/cube map to cubeUV conversion
3645
+ // equirect/cube map to PMREM conversion
3926
3646
 
3927
3647
  if ( isEquirectMap || isCubeMap ) {
3928
3648
 
@@ -4132,9 +3852,15 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) {
4132
3852
  const geometries = {};
4133
3853
  const wireframeAttributes = new WeakMap();
4134
3854
 
3855
+ const registry = new FinalizationRegistry( ( id ) => delete geometries[ id ] );
3856
+
4135
3857
  function onGeometryDispose( event ) {
4136
3858
 
4137
- const geometry = event.target;
3859
+ destroyGeometry( event.target );
3860
+
3861
+ }
3862
+
3863
+ function destroyGeometry( geometry ) {
4138
3864
 
4139
3865
  if ( geometry.index !== null ) {
4140
3866
 
@@ -4151,6 +3877,7 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) {
4151
3877
  geometry.removeEventListener( 'dispose', onGeometryDispose );
4152
3878
 
4153
3879
  delete geometries[ geometry.id ];
3880
+ registry.unregister( geometry );
4154
3881
 
4155
3882
  const attribute = wireframeAttributes.get( geometry );
4156
3883
 
@@ -4177,11 +3904,12 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) {
4177
3904
 
4178
3905
  function get( object, geometry ) {
4179
3906
 
4180
- if ( geometries[ geometry.id ] === true ) return geometry;
3907
+ if ( geometries[ geometry.id ] !== undefined ) return geometry;
4181
3908
 
4182
3909
  geometry.addEventListener( 'dispose', onGeometryDispose );
4183
3910
 
4184
- geometries[ geometry.id ] = true;
3911
+ geometries[ geometry.id ] = new WeakRef( geometry );
3912
+ registry.register( geometry, geometry.id, geometry );
4185
3913
 
4186
3914
  info.memory.geometries ++;
4187
3915
 
@@ -4205,8 +3933,6 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) {
4205
3933
 
4206
3934
  function updateWireframeAttribute( geometry ) {
4207
3935
 
4208
- const indices = [];
4209
-
4210
3936
  const geometryIndex = geometry.index;
4211
3937
  const geometryPosition = geometry.attributes.position;
4212
3938
  let version = 0;
@@ -4217,41 +3943,49 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) {
4217
3943
 
4218
3944
  }
4219
3945
 
3946
+ const count = geometryIndex !== null ? geometryIndex.array.length : ( geometryPosition.array.length / 3 ) - 1;
3947
+
3948
+ // check whether a 32 bit or 16 bit buffer is required to store the indices
3949
+ // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
3950
+ const IndexBufferAttribute = geometryPosition.count >= 65535 ? Uint32BufferAttribute : Uint16BufferAttribute;
3951
+ const attribute = new IndexBufferAttribute( Math.ceil( count / 3 ) * 6, 1 );
3952
+ const indices = attribute.array;
3953
+
4220
3954
  if ( geometryIndex !== null ) {
4221
3955
 
4222
3956
  const array = geometryIndex.array;
4223
3957
  version = geometryIndex.version;
4224
3958
 
4225
- for ( let i = 0, l = array.length; i < l; i += 3 ) {
3959
+ for ( let i = 0, j = 0; i < count; i += 3 ) {
4226
3960
 
4227
3961
  const a = array[ i + 0 ];
4228
3962
  const b = array[ i + 1 ];
4229
3963
  const c = array[ i + 2 ];
4230
3964
 
4231
- indices.push( a, b, b, c, c, a );
3965
+ indices[ j ++ ] = a; indices[ j ++ ] = b;
3966
+ indices[ j ++ ] = b; indices[ j ++ ] = c;
3967
+ indices[ j ++ ] = c; indices[ j ++ ] = a;
4232
3968
 
4233
3969
  }
4234
3970
 
4235
3971
  } else {
4236
3972
 
4237
- const array = geometryPosition.array;
4238
3973
  version = geometryPosition.version;
4239
3974
 
4240
- for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
3975
+ for ( let i = 0, j = 0; i < count; i += 3 ) {
4241
3976
 
4242
3977
  const a = i + 0;
4243
3978
  const b = i + 1;
4244
3979
  const c = i + 2;
4245
3980
 
4246
- indices.push( a, b, b, c, c, a );
3981
+ indices[ j ++ ] = a; indices[ j ++ ] = b;
3982
+ indices[ j ++ ] = b; indices[ j ++ ] = c;
3983
+ indices[ j ++ ] = c; indices[ j ++ ] = a;
4247
3984
 
4248
3985
  }
4249
3986
 
4250
3987
  }
4251
3988
 
4252
- // check whether a 32 bit or 16 bit buffer is required to store the indices
4253
- // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
4254
- const attribute = new ( geometryPosition.count >= 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
4255
3989
  attribute.version = version;
4256
3990
 
4257
3991
  // Updating index buffer in VAO now. See WebGLBindingStates
@@ -4298,12 +4032,26 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) {
4298
4032
 
4299
4033
  }
4300
4034
 
4035
+ function dispose() {
4036
+
4037
+ for ( const id in geometries ) {
4038
+
4039
+ const geometry = geometries[ id ].deref();
4040
+
4041
+ if ( geometry !== undefined ) destroyGeometry( geometry );
4042
+
4043
+ }
4044
+
4045
+ }
4046
+
4301
4047
  return {
4302
4048
 
4303
4049
  get: get,
4304
4050
  update: update,
4305
4051
 
4306
- getWireframeAttribute: getWireframeAttribute
4052
+ getWireframeAttribute: getWireframeAttribute,
4053
+
4054
+ dispose: dispose
4307
4055
 
4308
4056
  };
4309
4057
 
@@ -4725,6 +4473,9 @@ function WebGLOutput( type, width, height, antialias, depth, stencil ) {
4725
4473
  let targetA = null;
4726
4474
  let targetB = null;
4727
4475
 
4476
+ // scene depth for effects with needsDepthTexture set to true, allocated on demand
4477
+ let depthTexture = null;
4478
+
4728
4479
  // create fullscreen triangle geometry
4729
4480
  const geometry = new BufferGeometry();
4730
4481
  geometry.setAttribute( 'position', new Float32BufferAttribute( [ -1, 3, 0, -1, -1, 0, 3, -1, 0 ], 3 ) );
@@ -4829,10 +4580,40 @@ function WebGLOutput( type, width, height, antialias, depth, stencil ) {
4829
4580
 
4830
4581
  }
4831
4582
 
4583
+ // only store and resolve the scene depth if an effect reads it
4584
+
4585
+ const needsDepthTexture = depth === true && _effects.some( ( effect ) => effect.needsDepthTexture === true );
4586
+
4587
+ if ( needsDepthTexture !== ( targetScene.depthTexture !== null ) ) {
4588
+
4589
+ if ( needsDepthTexture === true && depthTexture === null ) {
4590
+
4591
+ depthTexture = new DepthTexture( width, height );
4592
+
4593
+ if ( stencil === true ) {
4594
+
4595
+ depthTexture.format = DepthStencilFormat;
4596
+ depthTexture.type = UnsignedInt248Type;
4597
+
4598
+ }
4599
+
4600
+ }
4601
+
4602
+ // release GPU resources so the scene target is rebuilt with the new depth setup
4603
+
4604
+ targetScene.dispose();
4605
+
4606
+ targetScene.depthTexture = needsDepthTexture ? depthTexture : null;
4607
+ targetScene.resolveDepthBuffer = needsDepthTexture;
4608
+ targetScene.storeMultisampledDepthBuffer = needsDepthTexture;
4609
+
4610
+ }
4611
+
4832
4612
  for ( let i = 0; i < _effects.length; i ++ ) {
4833
4613
 
4834
4614
  const effect = _effects[ i ];
4835
4615
  if ( effect.setSize ) effect.setSize( width, height );
4616
+ if ( needsDepthTexture && effect.needsDepthTexture === true && effect.setDepthTexture ) effect.setDepthTexture( depthTexture );
4836
4617
 
4837
4618
  }
4838
4619
 
@@ -5006,6 +4787,7 @@ function WebGLOutput( type, width, height, antialias, depth, stencil ) {
5006
4787
  const emptyTexture = /*@__PURE__*/ new Texture();
5007
4788
 
5008
4789
  const emptyShadowTexture = /*@__PURE__*/ new DepthTexture( 1, 1 );
4790
+ const emptyCubeShadowTexture = /*@__PURE__*/ new CubeDepthTexture( 1 );
5009
4791
 
5010
4792
  const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture();
5011
4793
  const empty3dTexture = /*@__PURE__*/ new Data3DTexture();
@@ -5509,6 +5291,19 @@ function setValueV4ui( gl, v ) {
5509
5291
  }
5510
5292
 
5511
5293
 
5294
+ function initShadowTexture( texture ) {
5295
+
5296
+ if ( texture.version === 0 ) {
5297
+
5298
+ texture.compareFunction = AlwaysCompare;
5299
+ texture.needsUpdate = true;
5300
+
5301
+ }
5302
+
5303
+ return texture;
5304
+
5305
+ }
5306
+
5512
5307
  // Single texture (2D / Cube)
5513
5308
 
5514
5309
  function setValueT1( gl, v, textures ) {
@@ -5527,8 +5322,7 @@ function setValueT1( gl, v, textures ) {
5527
5322
 
5528
5323
  if ( this.type === gl.SAMPLER_2D_SHADOW ) {
5529
5324
 
5530
- emptyShadowTexture.compareFunction = textures.isReversedDepthBuffer() ? GreaterEqualCompare : LessEqualCompare;
5531
- emptyTexture2D = emptyShadowTexture;
5325
+ emptyTexture2D = initShadowTexture( emptyShadowTexture );
5532
5326
 
5533
5327
  } else {
5534
5328
 
@@ -5568,7 +5362,19 @@ function setValueT6( gl, v, textures ) {
5568
5362
 
5569
5363
  }
5570
5364
 
5571
- textures.setTextureCube( v || emptyCubeTexture, unit );
5365
+ let emptyTextureCube;
5366
+
5367
+ if ( this.type === gl.SAMPLER_CUBE_SHADOW ) {
5368
+
5369
+ emptyTextureCube = initShadowTexture( emptyCubeShadowTexture );
5370
+
5371
+ } else {
5372
+
5373
+ emptyTextureCube = emptyCubeTexture;
5374
+
5375
+ }
5376
+
5377
+ textures.setTextureCube( v || emptyTextureCube, unit );
5572
5378
 
5573
5379
  }
5574
5380
 
@@ -5781,7 +5587,7 @@ function setValueT1Array( gl, v, textures ) {
5781
5587
 
5782
5588
  if ( this.type === gl.SAMPLER_2D_SHADOW ) {
5783
5589
 
5784
- emptyTexture2D = emptyShadowTexture;
5590
+ emptyTexture2D = initShadowTexture( emptyShadowTexture );
5785
5591
 
5786
5592
  } else {
5787
5593
 
@@ -5837,9 +5643,21 @@ function setValueT6Array( gl, v, textures ) {
5837
5643
 
5838
5644
  }
5839
5645
 
5646
+ let emptyTextureCube;
5647
+
5648
+ if ( this.type === gl.SAMPLER_CUBE_SHADOW ) {
5649
+
5650
+ emptyTextureCube = initShadowTexture( emptyCubeShadowTexture );
5651
+
5652
+ } else {
5653
+
5654
+ emptyTextureCube = emptyCubeTexture;
5655
+
5656
+ }
5657
+
5840
5658
  for ( let i = 0; i !== n; ++ i ) {
5841
5659
 
5842
- textures.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
5660
+ textures.setTextureCube( v[ i ] || emptyTextureCube, units[ i ] );
5843
5661
 
5844
5662
  }
5845
5663
 
@@ -6248,7 +6066,7 @@ function getTexelEncodingFunction( functionName, colorSpace ) {
6248
6066
 
6249
6067
  `vec4 ${functionName}( vec4 value ) {`,
6250
6068
 
6251
- ` return ${components[ 1 ]}( vec4( value.rgb * ${components[ 0 ]}, value.a ) );`,
6069
+ ` return ${components[ 1 ]}( vec4( ${components[ 0 ]} * value.rgb, value.a ) );`,
6252
6070
 
6253
6071
  '}',
6254
6072
 
@@ -6387,7 +6205,8 @@ function replaceLightNums( string, parameters ) {
6387
6205
  .replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )
6388
6206
  .replace( /NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g, parameters.numSpotLightShadowsWithMaps )
6389
6207
  .replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )
6390
- .replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );
6208
+ .replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows )
6209
+ .replace( /NUM_LIGHT_PROBE_GRIDS/g, parameters.numLightProbeGrids );
6391
6210
 
6392
6211
  }
6393
6212
 
@@ -6409,26 +6228,13 @@ function resolveIncludes( string ) {
6409
6228
 
6410
6229
  }
6411
6230
 
6412
- const shaderChunkMap = new Map();
6413
-
6414
6231
  function includeReplacer( match, include ) {
6415
6232
 
6416
- let string = ShaderChunk[ include ];
6233
+ const string = ShaderChunk[ include ];
6417
6234
 
6418
6235
  if ( string === undefined ) {
6419
6236
 
6420
- const newInclude = shaderChunkMap.get( include );
6421
-
6422
- if ( newInclude !== undefined ) {
6423
-
6424
- string = ShaderChunk[ newInclude ];
6425
- warn( 'WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.', include, newInclude );
6426
-
6427
- } else {
6428
-
6429
- throw new Error( 'THREE.WebGLProgram: Can not resolve #include <' + include + '>' );
6430
-
6431
- }
6237
+ throw new Error( 'THREE.WebGLProgram: Can not resolve #include <' + include + '>' );
6432
6238
 
6433
6239
  }
6434
6240
 
@@ -6514,20 +6320,6 @@ function generateShadowMapTypeDefine( parameters ) {
6514
6320
 
6515
6321
  }
6516
6322
 
6517
- const envMapTypeDefines = {
6518
- [ CubeReflectionMapping ]: 'ENVMAP_TYPE_CUBE',
6519
- [ CubeRefractionMapping ]: 'ENVMAP_TYPE_CUBE',
6520
- [ CubeUVReflectionMapping ]: 'ENVMAP_TYPE_CUBE_UV'
6521
- };
6522
-
6523
- function generateEnvMapTypeDefine( parameters ) {
6524
-
6525
- if ( parameters.envMap === false ) return 'ENVMAP_TYPE_CUBE';
6526
-
6527
- return envMapTypeDefines[ parameters.envMapMode ] || 'ENVMAP_TYPE_CUBE';
6528
-
6529
- }
6530
-
6531
6323
  const envMapModeDefines = {
6532
6324
  [ CubeRefractionMapping ]: 'ENVMAP_MODE_REFRACTION'
6533
6325
  };
@@ -6554,22 +6346,6 @@ function generateEnvMapBlendingDefine( parameters ) {
6554
6346
 
6555
6347
  }
6556
6348
 
6557
- function generateCubeUVSize( parameters ) {
6558
-
6559
- const imageHeight = parameters.envMapCubeUVHeight;
6560
-
6561
- if ( imageHeight === null ) return null;
6562
-
6563
- const maxMip = Math.log2( imageHeight ) - 2;
6564
-
6565
- const texelHeight = 1.0 / imageHeight;
6566
-
6567
- const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) );
6568
-
6569
- return { texelWidth, texelHeight, maxMip };
6570
-
6571
- }
6572
-
6573
6349
  function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
6574
6350
 
6575
6351
  // TODO Send this event to Three.js DevTools
@@ -6583,10 +6359,9 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
6583
6359
  let fragmentShader = parameters.fragmentShader;
6584
6360
 
6585
6361
  const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );
6586
- const envMapTypeDefine = generateEnvMapTypeDefine( parameters );
6362
+ const envMapTypeDefine = parameters.envMapPMREM === true ? 'ENVMAP_TYPE_PMREM' : 'ENVMAP_TYPE_CUBE';
6587
6363
  const envMapModeDefine = generateEnvMapModeDefine( parameters );
6588
6364
  const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );
6589
- const envMapCubeUVSize = generateCubeUVSize( parameters );
6590
6365
 
6591
6366
  const customVertexExtensions = generateVertexExtensions( parameters );
6592
6367
 
@@ -6668,6 +6443,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
6668
6443
  parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
6669
6444
  parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
6670
6445
  parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
6446
+ parameters.diffuseRoughnessMap ? '#define USE_DIFFUSE_ROUGHNESSMAP' : '',
6671
6447
 
6672
6448
  parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '',
6673
6449
  parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '',
@@ -6707,6 +6483,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
6707
6483
  parameters.clearcoatMapUv ? '#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv : '',
6708
6484
  parameters.clearcoatNormalMapUv ? '#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv : '',
6709
6485
  parameters.clearcoatRoughnessMapUv ? '#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv : '',
6486
+ parameters.diffuseRoughnessMapUv ? '#define DIFFUSE_ROUGHNESSMAP_UV ' + parameters.diffuseRoughnessMapUv : '',
6710
6487
 
6711
6488
  parameters.iridescenceMapUv ? '#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv : '',
6712
6489
  parameters.iridescenceThicknessMapUv ? '#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv : '',
@@ -6849,9 +6626,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
6849
6626
  parameters.envMap ? '#define ' + envMapTypeDefine : '',
6850
6627
  parameters.envMap ? '#define ' + envMapModeDefine : '',
6851
6628
  parameters.envMap ? '#define ' + envMapBlendingDefine : '',
6852
- envMapCubeUVSize ? '#define CUBEUV_TEXEL_WIDTH ' + envMapCubeUVSize.texelWidth : '',
6853
- envMapCubeUVSize ? '#define CUBEUV_TEXEL_HEIGHT ' + envMapCubeUVSize.texelHeight : '',
6854
- envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '',
6629
+ parameters.envMapPMREM ? '#define ENVMAP_MAX_LOD ' + parameters.envMapMaxLod + '.0' : '',
6630
+ parameters.envMapPMREM ? '#define ENVMAP_SIZE ' + parameters.envMapSize + '.0' : '',
6855
6631
  parameters.lightMap ? '#define USE_LIGHTMAP' : '',
6856
6632
  parameters.aoMap ? '#define USE_AOMAP' : '',
6857
6633
  parameters.bumpMap ? '#define USE_BUMPMAP' : '',
@@ -6869,6 +6645,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
6869
6645
  parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
6870
6646
  parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
6871
6647
 
6648
+ parameters.diffuseRoughness ? '#define USE_DIFFUSE_ROUGHNESS' : '',
6649
+ parameters.diffuseRoughnessMap ? '#define USE_DIFFUSE_ROUGHNESSMAP' : '',
6872
6650
  parameters.dispersion ? '#define USE_DISPERSION' : '',
6873
6651
  parameters.retroreflection ? '#define USE_RETROREFLECTION' : '',
6874
6652
 
@@ -6918,7 +6696,6 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
6918
6696
 
6919
6697
  parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '',
6920
6698
 
6921
- parameters.numLightProbeGrids > 0 ? '#define USE_LIGHT_PROBES_GRID' : '',
6922
6699
 
6923
6700
  parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '',
6924
6701
  parameters.decodeVideoTextureEmissive ? '#define DECODE_VIDEO_TEXTURE_EMISSIVE' : '',
@@ -7324,8 +7101,6 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7324
7101
 
7325
7102
  const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
7326
7103
 
7327
- let precision = capabilities.precision;
7328
-
7329
7104
  const shaderIDs = {
7330
7105
  MeshDepthMaterial: 'depth',
7331
7106
  MeshDistanceMaterial: 'distance',
@@ -7362,13 +7137,14 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7362
7137
 
7363
7138
  const usePMREM = material.isMeshStandardMaterial || ( material.isMeshLambertMaterial && ! material.envMap ) || ( material.isMeshPhongMaterial && ! material.envMap );
7364
7139
  const envMap = environments.get( material.envMap || environment, usePMREM );
7365
- const envMapCubeUVHeight = ( !! envMap ) && ( envMap.mapping === CubeUVReflectionMapping ) ? envMap.image.height : null;
7366
7140
 
7367
7141
  const shaderID = shaderIDs[ material.type ];
7368
7142
 
7369
7143
  // heuristics to create shader parameters according to lights in the scene
7370
7144
  // (not to blow over maxLights budget)
7371
7145
 
7146
+ let precision = capabilities.precision;
7147
+
7372
7148
  if ( material.precision !== null ) {
7373
7149
 
7374
7150
  precision = capabilities.getMaxPrecision( material.precision );
@@ -7428,6 +7204,7 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7428
7204
  const HAS_MAP = !! material.map;
7429
7205
  const HAS_MATCAP = !! material.matcap;
7430
7206
  const HAS_ENVMAP = !! envMap;
7207
+ const HAS_PMREM = HAS_ENVMAP && envMap.isPMREMTexture === true;
7431
7208
  const HAS_AOMAP = !! material.aoMap;
7432
7209
  const HAS_LIGHTMAP = !! material.lightMap;
7433
7210
  const HAS_BUMPMAP = !! material.bumpMap && material.wireframe === false;
@@ -7440,6 +7217,7 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7440
7217
 
7441
7218
  const HAS_ANISOTROPY = material.anisotropy > 0;
7442
7219
  const HAS_CLEARCOAT = material.clearcoat > 0;
7220
+ const HAS_DIFFUSE_ROUGHNESS = material.diffuseRoughness > 0;
7443
7221
  const HAS_DISPERSION = material.dispersion > 0;
7444
7222
  const HAS_RETROREFLECTION = material.retroreflectivity > 0;
7445
7223
  const HAS_IRIDESCENCE = material.iridescence > 0;
@@ -7451,6 +7229,7 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7451
7229
  const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap;
7452
7230
  const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap;
7453
7231
  const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap;
7232
+ const HAS_DIFFUSE_ROUGHNESSMAP = HAS_DIFFUSE_ROUGHNESS && !! material.diffuseRoughnessMap;
7454
7233
 
7455
7234
  const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap;
7456
7235
  const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap;
@@ -7487,6 +7266,8 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7487
7266
 
7488
7267
  }
7489
7268
 
7269
+ const envMapMipmaps = HAS_PMREM ? ( envMap.isCompressedCubeTexture ? envMap.image[ 0 ].mipmaps : envMap.mipmaps ) : null;
7270
+
7490
7271
  const parameters = {
7491
7272
 
7492
7273
  shaderID: shaderID,
@@ -7518,7 +7299,9 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7518
7299
  matcap: HAS_MATCAP,
7519
7300
  envMap: HAS_ENVMAP,
7520
7301
  envMapMode: HAS_ENVMAP && envMap.mapping,
7521
- envMapCubeUVHeight: envMapCubeUVHeight,
7302
+ envMapPMREM: HAS_PMREM,
7303
+ envMapMaxLod: HAS_PMREM ? envMapMipmaps.length - 1 : null,
7304
+ envMapSize: HAS_PMREM ? envMapMipmaps[ 0 ].width : null,
7522
7305
  aoMap: HAS_AOMAP,
7523
7306
  lightMap: HAS_LIGHTMAP,
7524
7307
  bumpMap: HAS_BUMPMAP,
@@ -7541,6 +7324,8 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7541
7324
  clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP,
7542
7325
  clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP,
7543
7326
 
7327
+ diffuseRoughness: HAS_DIFFUSE_ROUGHNESS,
7328
+ diffuseRoughnessMap: HAS_DIFFUSE_ROUGHNESSMAP,
7544
7329
  dispersion: HAS_DISPERSION,
7545
7330
  retroreflection: HAS_RETROREFLECTION,
7546
7331
 
@@ -7588,6 +7373,7 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7588
7373
  clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ),
7589
7374
  clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ),
7590
7375
  clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ),
7376
+ diffuseRoughnessMapUv: HAS_DIFFUSE_ROUGHNESSMAP && getChannel( material.diffuseRoughnessMap.channel ),
7591
7377
 
7592
7378
  iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ),
7593
7379
  iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ),
@@ -7654,7 +7440,7 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7654
7440
 
7655
7441
  numLightProbes: lights.numLightProbes,
7656
7442
 
7657
- numLightProbeGrids: lightProbeGrids.length,
7443
+ numLightProbeGrids: lightProbeGrids.filter( grid => grid.texture !== null ).length,
7658
7444
 
7659
7445
  numClippingPlanes: clipping.numPlanes,
7660
7446
  numClipIntersection: clipping.numIntersection,
@@ -7745,7 +7531,9 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7745
7531
  array.push( parameters.precision );
7746
7532
  array.push( parameters.outputColorSpace );
7747
7533
  array.push( parameters.envMapMode );
7748
- array.push( parameters.envMapCubeUVHeight );
7534
+ array.push( parameters.envMapPMREM );
7535
+ array.push( parameters.envMapMaxLod );
7536
+ array.push( parameters.envMapSize );
7749
7537
  array.push( parameters.mapUv );
7750
7538
  array.push( parameters.alphaMapUv );
7751
7539
  array.push( parameters.lightMapUv );
@@ -7760,6 +7548,7 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7760
7548
  array.push( parameters.clearcoatMapUv );
7761
7549
  array.push( parameters.clearcoatNormalMapUv );
7762
7550
  array.push( parameters.clearcoatRoughnessMapUv );
7551
+ array.push( parameters.diffuseRoughnessMapUv );
7763
7552
  array.push( parameters.iridescenceMapUv );
7764
7553
  array.push( parameters.iridescenceThicknessMapUv );
7765
7554
  array.push( parameters.sheenColorMapUv );
@@ -7773,7 +7562,6 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7773
7562
  array.push( parameters.fogExp2 );
7774
7563
  array.push( parameters.sizeAttenuation );
7775
7564
  array.push( parameters.morphTargetsCount );
7776
- array.push( parameters.morphAttributeCount );
7777
7565
  array.push( parameters.numSunLights );
7778
7566
  array.push( parameters.numDirLights );
7779
7567
  array.push( parameters.numPointLights );
@@ -7787,6 +7575,7 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7787
7575
  array.push( parameters.numSpotLightShadows );
7788
7576
  array.push( parameters.numSpotLightShadowsWithMaps );
7789
7577
  array.push( parameters.numLightProbes );
7578
+ array.push( parameters.numLightProbeGrids );
7790
7579
  array.push( parameters.shadowMapType );
7791
7580
  array.push( parameters.toneMapping );
7792
7581
  array.push( parameters.numClippingPlanes );
@@ -7841,6 +7630,8 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
7841
7630
  _programLayers.enable( 19 );
7842
7631
  if ( parameters.retroreflection )
7843
7632
  _programLayers.enable( 24 );
7633
+ if ( parameters.diffuseRoughness )
7634
+ _programLayers.enable( 25 );
7844
7635
  if ( parameters.batchingColor )
7845
7636
  _programLayers.enable( 20 );
7846
7637
  if ( parameters.gradientMap )
@@ -8965,19 +8756,21 @@ function WebGLRenderState( extensions ) {
8965
8756
 
8966
8757
  function pushLight( light ) {
8967
8758
 
8968
- lightsArray.push( light );
8759
+ if ( light.isLightProbeGrid ) {
8969
8760
 
8970
- }
8761
+ lightProbeGridArray.push( light );
8971
8762
 
8972
- function pushShadow( shadowLight ) {
8763
+ } else {
8973
8764
 
8974
- shadowsArray.push( shadowLight );
8765
+ lightsArray.push( light );
8766
+
8767
+ }
8975
8768
 
8976
8769
  }
8977
8770
 
8978
- function pushLightProbeGrid( volume ) {
8771
+ function pushShadow( shadowLight ) {
8979
8772
 
8980
- lightProbeGridArray.push( volume );
8773
+ shadowsArray.push( shadowLight );
8981
8774
 
8982
8775
  }
8983
8776
 
@@ -8985,6 +8778,8 @@ function WebGLRenderState( extensions ) {
8985
8778
 
8986
8779
  lights.setup( lightsArray );
8987
8780
 
8781
+ lightProbeGridArray.sort( ( a, b ) => a.priority - b.priority || a.id - b.id );
8782
+
8988
8783
  }
8989
8784
 
8990
8785
  function setupLightsView( camera ) {
@@ -9013,8 +8808,7 @@ function WebGLRenderState( extensions ) {
9013
8808
  setupLightsView: setupLightsView,
9014
8809
 
9015
8810
  pushLight: pushLight,
9016
- pushShadow: pushShadow,
9017
- pushLightProbeGrid: pushLightProbeGrid
8811
+ pushShadow: pushShadow
9018
8812
  };
9019
8813
 
9020
8814
  }
@@ -9341,6 +9135,8 @@ function WebGLShadowMap( renderer, objects, capabilities ) {
9341
9135
 
9342
9136
  if ( light.isPointLight !== true ) shadow.updateMatrices( light, camera );
9343
9137
 
9138
+ const layers = ( shadow.camera.layers.mask & 0xFFFFFFFE ) !== 0 ? shadow.camera.layers : camera.layers;
9139
+
9344
9140
  for ( let face = 0; face < faceCount; face ++ ) {
9345
9141
 
9346
9142
  const shadowCamera = shadow.getCamera( face );
@@ -9406,7 +9202,7 @@ function WebGLShadowMap( renderer, objects, capabilities ) {
9406
9202
 
9407
9203
  _frustum = shadow.getFrustum( face );
9408
9204
 
9409
- renderObject( scene, camera, shadowCamera, light, this.type );
9205
+ renderObject( scene, camera, shadowCamera, light, layers, this.type );
9410
9206
 
9411
9207
  }
9412
9208
 
@@ -9566,11 +9362,11 @@ function WebGLShadowMap( renderer, objects, capabilities ) {
9566
9362
 
9567
9363
  }
9568
9364
 
9569
- function renderObject( object, camera, shadowCamera, light, type ) {
9365
+ function renderObject( object, camera, shadowCamera, light, layers, type ) {
9570
9366
 
9571
9367
  if ( object.visible === false ) return;
9572
9368
 
9573
- const visible = object.layers.test( camera.layers );
9369
+ const visible = object.layers.test( layers );
9574
9370
 
9575
9371
  if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
9576
9372
 
@@ -9624,7 +9420,7 @@ function WebGLShadowMap( renderer, objects, capabilities ) {
9624
9420
 
9625
9421
  for ( let i = 0, l = children.length; i < l; i ++ ) {
9626
9422
 
9627
- renderObject( children[ i ], camera, shadowCamera, light, type );
9423
+ renderObject( children[ i ], camera, shadowCamera, light, layers, type );
9628
9424
 
9629
9425
  }
9630
9426
 
@@ -10004,7 +9800,7 @@ function WebGLState( gl, extensions ) {
10004
9800
  const depthBuffer = new DepthBuffer();
10005
9801
  const stencilBuffer = new StencilBuffer();
10006
9802
 
10007
- const uboBindings = new WeakMap();
9803
+ let uboBindings = {};
10008
9804
  const uboProgramMap = new WeakMap();
10009
9805
 
10010
9806
  let enabledCapabilities = {};
@@ -10526,6 +10322,7 @@ function WebGLState( gl, extensions ) {
10526
10322
  if ( depthBuffer.getReversed() ) {
10527
10323
 
10528
10324
  factor = - factor;
10325
+ units = - units;
10529
10326
 
10530
10327
  }
10531
10328
 
@@ -10835,23 +10632,25 @@ function WebGLState( gl, extensions ) {
10835
10632
 
10836
10633
  blockIndex = gl.getUniformBlockIndex( program, uniformsGroup.name );
10837
10634
 
10635
+ // use the block index as the binding point
10636
+ gl.uniformBlockBinding( program, blockIndex, blockIndex );
10637
+
10838
10638
  mapping.set( uniformsGroup, blockIndex );
10839
10639
 
10840
10640
  }
10841
10641
 
10842
10642
  }
10843
10643
 
10844
- function uniformBlockBinding( uniformsGroup, program ) {
10644
+ function uniformBlockBinding( uniformsGroup, program, buffer ) {
10845
10645
 
10846
10646
  const mapping = uboProgramMap.get( program );
10847
10647
  const blockIndex = mapping.get( uniformsGroup );
10848
10648
 
10849
- if ( uboBindings.get( program ) !== blockIndex ) {
10649
+ if ( uboBindings[ blockIndex ] !== buffer ) {
10850
10650
 
10851
- // bind shader specific block index to global block point
10852
- gl.uniformBlockBinding( program, blockIndex, uniformsGroup.__bindingPointIndex );
10651
+ gl.bindBufferBase( gl.UNIFORM_BUFFER, blockIndex, buffer );
10853
10652
 
10854
- uboBindings.set( program, blockIndex );
10653
+ uboBindings[ blockIndex ] = buffer;
10855
10654
 
10856
10655
  }
10857
10656
 
@@ -10932,6 +10731,7 @@ function WebGLState( gl, extensions ) {
10932
10731
  currentBoundTextures = {};
10933
10732
 
10934
10733
  currentBoundFramebuffers = {};
10734
+ uboBindings = {};
10935
10735
  currentDrawbuffers = new WeakMap();
10936
10736
  defaultDrawbuffers = [];
10937
10737
 
@@ -11034,6 +10834,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
11034
10834
 
11035
10835
  const _sources = new WeakMap(); // maps WebglTexture objects to instances of TextureSource
11036
10836
 
10837
+ const _tracked = new Set();
10838
+ const _registry = new FinalizationRegistry( ( ref ) => _tracked.delete( ref ) );
10839
+
11037
10840
  // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,
11038
10841
  // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")!
11039
10842
  // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).
@@ -11317,7 +11120,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
11317
11120
 
11318
11121
  return Math.log2( Math.max( image.width, image.height ) ) + 1;
11319
11122
 
11320
- } else if ( texture.mipmaps !== undefined && texture.mipmaps.length > 0 ) {
11123
+ } else if ( texture.mipmaps.length > 0 ) {
11321
11124
 
11322
11125
  // user-defined mipmaps
11323
11126
 
@@ -11339,12 +11142,45 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
11339
11142
 
11340
11143
  //
11341
11144
 
11145
+ function track( object ) {
11146
+
11147
+ const ref = new WeakRef( object );
11148
+
11149
+ properties.get( object ).__ref = ref;
11150
+
11151
+ _tracked.add( ref );
11152
+ _registry.register( object, ref, ref );
11153
+
11154
+ }
11155
+
11156
+ function untrack( object ) {
11157
+
11158
+ const ref = properties.get( object ).__ref;
11159
+
11160
+ if ( ref === undefined ) return;
11161
+
11162
+ _tracked.delete( ref );
11163
+ _registry.unregister( ref );
11164
+
11165
+ }
11166
+
11342
11167
  function onTextureDispose( event ) {
11343
11168
 
11344
- const texture = event.target;
11169
+ destroyTexture( event.target );
11170
+
11171
+ }
11172
+
11173
+ function onRenderTargetDispose( event ) {
11174
+
11175
+ destroyRenderTarget( event.target );
11176
+
11177
+ }
11178
+
11179
+ function destroyTexture( texture ) {
11345
11180
 
11346
11181
  texture.removeEventListener( 'dispose', onTextureDispose );
11347
11182
 
11183
+ untrack( texture );
11348
11184
  deallocateTexture( texture );
11349
11185
 
11350
11186
  if ( texture.isVideoTexture ) {
@@ -11361,16 +11197,40 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
11361
11197
 
11362
11198
  }
11363
11199
 
11364
- function onRenderTargetDispose( event ) {
11365
-
11366
- const renderTarget = event.target;
11200
+ function destroyRenderTarget( renderTarget ) {
11367
11201
 
11368
11202
  renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
11369
11203
 
11204
+ untrack( renderTarget );
11370
11205
  deallocateRenderTarget( renderTarget );
11371
11206
 
11372
11207
  }
11373
11208
 
11209
+ function dispose() {
11210
+
11211
+ for ( const ref of _tracked ) {
11212
+
11213
+ const object = ref.deref();
11214
+
11215
+ if ( object === undefined ) continue;
11216
+
11217
+ if ( object.isRenderTarget === true ) {
11218
+
11219
+ destroyRenderTarget( object );
11220
+
11221
+ } else {
11222
+
11223
+ destroyTexture( object );
11224
+
11225
+ }
11226
+
11227
+ }
11228
+
11229
+ _tracked.clear();
11230
+ _htmlTextures.clear();
11231
+
11232
+ }
11233
+
11374
11234
  //
11375
11235
 
11376
11236
  function deallocateTexture( texture ) {
@@ -11428,13 +11288,13 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
11428
11288
 
11429
11289
  const renderTargetProperties = properties.get( renderTarget );
11430
11290
 
11431
- if ( renderTarget.depthTexture ) {
11291
+ if ( renderTargetProperties.__depthDisposeCallback ) renderTargetProperties.__depthDisposeCallback();
11432
11292
 
11433
- renderTarget.depthTexture.dispose();
11293
+ const depthTexture = renderTarget.depthTexture;
11434
11294
 
11435
- properties.remove( renderTarget.depthTexture );
11295
+ // only destroy depth texture the render target owns
11436
11296
 
11437
- }
11297
+ if ( depthTexture && depthTexture.renderTarget === renderTarget ) destroyTexture( depthTexture );
11438
11298
 
11439
11299
  if ( renderTarget.isWebGLCubeRenderTarget ) {
11440
11300
 
@@ -11557,6 +11417,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
11557
11417
  array.push( texture.format );
11558
11418
  array.push( texture.type );
11559
11419
  array.push( texture.generateMipmaps );
11420
+ array.push( texture.mipmapsAutoUpdate );
11560
11421
  array.push( texture.premultiplyAlpha );
11561
11422
  array.push( texture.flipY );
11562
11423
  array.push( texture.unpackAlignment );
@@ -11641,7 +11502,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
11641
11502
 
11642
11503
  const textureProperties = properties.get( texture );
11643
11504
 
11644
- if ( texture.isCubeDepthTexture !== true && texture.version > 0 && textureProperties.__version !== texture.version ) {
11505
+ if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
11645
11506
 
11646
11507
  uploadCubeTexture( textureProperties, texture, slot );
11647
11508
  return;
@@ -11735,6 +11596,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
11735
11596
  textureProperties.__webglInit = true;
11736
11597
 
11737
11598
  texture.addEventListener( 'dispose', onTextureDispose );
11599
+ track( texture );
11738
11600
 
11739
11601
  }
11740
11602
 
@@ -12406,7 +12268,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
12406
12268
 
12407
12269
  }
12408
12270
 
12409
- if ( textureNeedsGenerateMipmaps( texture ) ) {
12271
+ if ( textureNeedsGenerateMipmaps( texture ) && texture.mipmapsAutoUpdate === true ) {
12410
12272
 
12411
12273
  generateMipmap( textureType );
12412
12274
 
@@ -12469,8 +12331,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
12469
12331
 
12470
12332
  const image = cubeImage[ 0 ],
12471
12333
  glFormat = utils.convert( texture.format, texture.colorSpace ),
12472
- glType = utils.convert( texture.type ),
12473
- glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.normalized, texture.colorSpace );
12334
+ glType = utils.convert( texture.type );
12335
+
12336
+ let glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.normalized, texture.colorSpace );
12474
12337
 
12475
12338
  const useTexStorage = ( texture.isVideoTexture !== true );
12476
12339
  const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true );
@@ -12481,7 +12344,31 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
12481
12344
 
12482
12345
  let mipmaps;
12483
12346
 
12484
- if ( isCompressed ) {
12347
+ if ( texture.isDepthTexture ) {
12348
+
12349
+ glInternalFormat = getInternalDepthFormat( texture.format === DepthStencilFormat, texture.type );
12350
+
12351
+ //
12352
+
12353
+ if ( allocateMemory ) {
12354
+
12355
+ if ( useTexStorage ) {
12356
+
12357
+ state.texStorage2D( _gl.TEXTURE_CUBE_MAP, 1, glInternalFormat, image.width, image.height );
12358
+
12359
+ } else {
12360
+
12361
+ for ( let i = 0; i < 6; i ++ ) {
12362
+
12363
+ state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
12364
+
12365
+ }
12366
+
12367
+ }
12368
+
12369
+ }
12370
+
12371
+ } else if ( isCompressed ) {
12485
12372
 
12486
12373
  if ( useTexStorage && allocateMemory ) {
12487
12374
 
@@ -12642,7 +12529,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
12642
12529
 
12643
12530
  }
12644
12531
 
12645
- if ( textureNeedsGenerateMipmaps( texture ) ) {
12532
+ if ( textureNeedsGenerateMipmaps( texture ) && texture.mipmapsAutoUpdate === true ) {
12646
12533
 
12647
12534
  // We assume images for cube map have the same size.
12648
12535
  generateMipmap( _gl.TEXTURE_CUBE_MAP );
@@ -12786,57 +12673,21 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
12786
12673
  textureProperties.__renderTarget = renderTarget;
12787
12674
 
12788
12675
  // upload an empty depth texture with framebuffer size
12676
+ const image = isCube ? renderTarget.depthTexture.image[ 0 ] : renderTarget.depthTexture.image;
12677
+
12789
12678
  if ( ! textureProperties.__webglTexture ||
12790
- renderTarget.depthTexture.image.width !== renderTarget.width ||
12791
- renderTarget.depthTexture.image.height !== renderTarget.height ) {
12679
+ image.width !== renderTarget.width ||
12680
+ image.height !== renderTarget.height ) {
12792
12681
 
12793
- renderTarget.depthTexture.image.width = renderTarget.width;
12794
- renderTarget.depthTexture.image.height = renderTarget.height;
12682
+ image.width = renderTarget.width;
12683
+ image.height = renderTarget.height;
12795
12684
  renderTarget.depthTexture.needsUpdate = true;
12796
12685
 
12797
12686
  }
12798
12687
 
12799
12688
  if ( isCube ) {
12800
12689
 
12801
- // For cube depth textures, initialize and bind without uploading image data
12802
- if ( textureProperties.__webglInit === undefined ) {
12803
-
12804
- textureProperties.__webglInit = true;
12805
- renderTarget.depthTexture.addEventListener( 'dispose', onTextureDispose );
12806
-
12807
- }
12808
-
12809
- // Only create and allocate storage once
12810
- if ( textureProperties.__webglTexture === undefined ) {
12811
-
12812
- textureProperties.__webglTexture = _gl.createTexture();
12813
-
12814
- state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );
12815
- setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.depthTexture );
12816
-
12817
- // Allocate storage for all 6 faces with correct depth texture format
12818
- const glFormat = utils.convert( renderTarget.depthTexture.format );
12819
- const glType = utils.convert( renderTarget.depthTexture.type );
12820
-
12821
- // Use proper internal format for depth textures
12822
- let glInternalFormat;
12823
- if ( renderTarget.depthTexture.format === DepthFormat ) {
12824
-
12825
- glInternalFormat = _gl.DEPTH_COMPONENT24;
12826
-
12827
- } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
12828
-
12829
- glInternalFormat = _gl.DEPTH24_STENCIL8;
12830
-
12831
- }
12832
-
12833
- for ( let i = 0; i < 6; i ++ ) {
12834
-
12835
- _gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
12836
-
12837
- }
12838
-
12839
- }
12690
+ setTextureCube( renderTarget.depthTexture, 0 );
12840
12691
 
12841
12692
  } else {
12842
12693
 
@@ -12934,7 +12785,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
12934
12785
 
12935
12786
  const mipmaps = renderTarget.texture.mipmaps;
12936
12787
 
12937
- if ( mipmaps && mipmaps.length > 0 ) {
12788
+ if ( mipmaps.length > 0 ) {
12938
12789
 
12939
12790
  setupDepthTexture( renderTargetProperties.__webglFramebuffer[ 0 ], renderTarget, 0 );
12940
12791
 
@@ -12977,7 +12828,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
12977
12828
 
12978
12829
  const mipmaps = renderTarget.texture.mipmaps;
12979
12830
 
12980
- if ( mipmaps && mipmaps.length > 0 ) {
12831
+ if ( mipmaps.length > 0 ) {
12981
12832
 
12982
12833
  state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ 0 ] );
12983
12834
 
@@ -13038,6 +12889,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
13038
12889
  const textureProperties = properties.get( texture );
13039
12890
 
13040
12891
  renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
12892
+ track( renderTarget );
13041
12893
 
13042
12894
  const textures = renderTarget.textures;
13043
12895
 
@@ -13065,7 +12917,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
13065
12917
 
13066
12918
  for ( let i = 0; i < 6; i ++ ) {
13067
12919
 
13068
- if ( texture.mipmaps && texture.mipmaps.length > 0 ) {
12920
+ if ( texture.mipmaps.length > 0 ) {
13069
12921
 
13070
12922
  renderTargetProperties.__webglFramebuffer[ i ] = [];
13071
12923
 
@@ -13085,7 +12937,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
13085
12937
 
13086
12938
  } else {
13087
12939
 
13088
- if ( texture.mipmaps && texture.mipmaps.length > 0 ) {
12940
+ if ( texture.mipmaps.length > 0 ) {
13089
12941
 
13090
12942
  renderTargetProperties.__webglFramebuffer = [];
13091
12943
 
@@ -13167,7 +13019,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
13167
13019
 
13168
13020
  for ( let i = 0; i < 6; i ++ ) {
13169
13021
 
13170
- if ( texture.mipmaps && texture.mipmaps.length > 0 ) {
13022
+ if ( texture.mipmaps.length > 0 ) {
13171
13023
 
13172
13024
  for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
13173
13025
 
@@ -13187,6 +13039,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
13187
13039
 
13188
13040
  generateMipmap( _gl.TEXTURE_CUBE_MAP );
13189
13041
 
13042
+ } else if ( texture.mipmaps.length > 0 ) {
13043
+
13044
+ // Limit the max level to keep partial mip chains complete.
13045
+ _gl.texParameteri( _gl.TEXTURE_CUBE_MAP, _gl.TEXTURE_MAX_LEVEL, texture.mipmaps.length - 1 );
13046
+
13190
13047
  }
13191
13048
 
13192
13049
  state.unbindTexture();
@@ -13233,7 +13090,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
13233
13090
  state.bindTexture( glTextureType, textureProperties.__webglTexture );
13234
13091
  setTextureParameters( glTextureType, texture );
13235
13092
 
13236
- if ( texture.mipmaps && texture.mipmaps.length > 0 ) {
13093
+ if ( texture.mipmaps.length > 0 ) {
13237
13094
 
13238
13095
  for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
13239
13096
 
@@ -13251,6 +13108,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
13251
13108
 
13252
13109
  generateMipmap( glTextureType );
13253
13110
 
13111
+ } else if ( texture.mipmaps.length > 0 ) {
13112
+
13113
+ // Limit the max level to keep partial mip chains complete.
13114
+ _gl.texParameteri( glTextureType, _gl.TEXTURE_MAX_LEVEL, texture.mipmaps.length - 1 );
13115
+
13254
13116
  }
13255
13117
 
13256
13118
  state.unbindTexture();
@@ -13275,7 +13137,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
13275
13137
 
13276
13138
  const texture = textures[ i ];
13277
13139
 
13278
- if ( textureNeedsGenerateMipmaps( texture ) ) {
13140
+ if ( textureNeedsGenerateMipmaps( texture ) && texture.mipmapsAutoUpdate === true ) {
13279
13141
 
13280
13142
  const targetType = getTargetType( renderTarget );
13281
13143
  const webglTexture = properties.get( texture ).__webglTexture;
@@ -13291,7 +13153,6 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
13291
13153
  }
13292
13154
 
13293
13155
  const invalidationArrayRead = [];
13294
- const invalidationArrayDraw = [];
13295
13156
 
13296
13157
  function updateMultisampleRenderTarget( renderTarget ) {
13297
13158
 
@@ -13326,7 +13187,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
13326
13187
 
13327
13188
  const mipmaps = renderTarget.texture.mipmaps;
13328
13189
 
13329
- if ( mipmaps && mipmaps.length > 0 ) {
13190
+ if ( mipmaps.length > 0 ) {
13330
13191
 
13331
13192
  state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ 0 ] );
13332
13193
 
@@ -13362,16 +13223,12 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
13362
13223
  if ( supportsInvalidateFramebuffer === true ) {
13363
13224
 
13364
13225
  invalidationArrayRead.length = 0;
13365
- invalidationArrayDraw.length = 0;
13366
13226
 
13367
13227
  invalidationArrayRead.push( _gl.COLOR_ATTACHMENT0 + i );
13368
13228
 
13369
13229
  if ( renderTarget.depthBuffer && renderTarget.storeMultisampledDepthBuffer === false ) {
13370
13230
 
13371
13231
  invalidationArrayRead.push( depthStyle );
13372
- invalidationArrayDraw.push( depthStyle );
13373
-
13374
- _gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, invalidationArrayDraw );
13375
13232
 
13376
13233
  }
13377
13234
 
@@ -13525,12 +13382,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
13525
13382
  this.setupDepthRenderbuffer = setupDepthRenderbuffer;
13526
13383
  this.setupFrameBufferTexture = setupFrameBufferTexture;
13527
13384
  this.useMultisampledRTT = useMultisampledRTT;
13528
-
13529
- this.isReversedDepthBuffer = function () {
13530
-
13531
- return state.buffers.depth.getReversed();
13532
-
13533
- };
13385
+ this.dispose = dispose;
13534
13386
 
13535
13387
  }
13536
13388
 
@@ -14513,82 +14365,6 @@ class WebXRManager extends EventDispatcher {
14513
14365
 
14514
14366
  //
14515
14367
 
14516
- const cameraLPos = new Vector3();
14517
- const cameraRPos = new Vector3();
14518
-
14519
- /**
14520
- * Assumes 2 cameras that are parallel and share an X-axis, and that
14521
- * the cameras' projection and world matrices have already been set.
14522
- * And that near and far planes are identical for both cameras.
14523
- * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
14524
- *
14525
- * @param {ArrayCamera} camera - The camera to update.
14526
- * @param {PerspectiveCamera} cameraL - The left camera.
14527
- * @param {PerspectiveCamera} cameraR - The right camera.
14528
- */
14529
- function setProjectionFromUnion( camera, cameraL, cameraR ) {
14530
-
14531
- cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
14532
- cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
14533
-
14534
- const ipd = cameraLPos.distanceTo( cameraRPos );
14535
-
14536
- const projL = cameraL.projectionMatrix.elements;
14537
- const projR = cameraR.projectionMatrix.elements;
14538
-
14539
- // VR systems will have identical far and near planes, and
14540
- // most likely identical top and bottom frustum extents.
14541
- // Use the left camera for these values.
14542
- const near = projL[ 14 ] / ( projL[ 10 ] - 1 );
14543
- const far = projL[ 14 ] / ( projL[ 10 ] + 1 );
14544
- const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
14545
- const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
14546
-
14547
- const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
14548
- const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
14549
- const left = near * leftFov;
14550
- const right = near * rightFov;
14551
-
14552
- // Calculate the new camera's position offset from the
14553
- // left camera. xOffset should be roughly half `ipd`.
14554
- const zOffset = ipd / ( - leftFov + rightFov );
14555
- const xOffset = zOffset * - leftFov;
14556
-
14557
- // TODO: Better way to apply this offset?
14558
- cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
14559
- camera.translateX( xOffset );
14560
- camera.translateZ( zOffset );
14561
- camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
14562
- camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
14563
-
14564
- // Check if the projection uses an infinite far plane.
14565
- if ( projL[ 10 ] === -1 ) {
14566
-
14567
- // Use the projection matrix from the left eye.
14568
- // The camera offset is sufficient to include the view volumes
14569
- // of both eyes (assuming symmetric projections).
14570
- camera.projectionMatrix.copy( cameraL.projectionMatrix );
14571
- camera.projectionMatrixInverse.copy( cameraL.projectionMatrixInverse );
14572
-
14573
- } else {
14574
-
14575
- // Find the union of the frustum values of the cameras and scale
14576
- // the values so that the near plane's position does not change in world space,
14577
- // although must now be relative to the new union camera.
14578
- const near2 = near + zOffset;
14579
- const far2 = far + zOffset;
14580
- const left2 = left - xOffset;
14581
- const right2 = right + ( ipd - xOffset );
14582
- const top2 = topFov * far / far2 * near2;
14583
- const bottom2 = bottomFov * far / far2 * near2;
14584
-
14585
- camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
14586
- camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert();
14587
-
14588
- }
14589
-
14590
- }
14591
-
14592
14368
  function updateCamera( camera, parent ) {
14593
14369
 
14594
14370
  if ( parent === null ) {
@@ -14661,19 +14437,8 @@ class WebXRManager extends EventDispatcher {
14661
14437
 
14662
14438
  }
14663
14439
 
14664
- // update projection matrix for proper view frustum culling
14665
-
14666
- if ( cameras.length === 2 ) {
14667
-
14668
- setProjectionFromUnion( cameraXR, cameraL, cameraR );
14669
-
14670
- } else {
14671
-
14672
- // assume single camera setup (AR)
14673
-
14674
- cameraXR.projectionMatrix.copy( cameraL.projectionMatrix );
14675
-
14676
- }
14440
+ cameraXR.projectionMatrix.copy( cameraL.projectionMatrix );
14441
+ cameraXR.projectionMatrixInverse.copy( cameraL.projectionMatrixInverse );
14677
14442
 
14678
14443
  // update user camera and its children
14679
14444
 
@@ -14724,6 +14489,9 @@ class WebXRManager extends EventDispatcher {
14724
14489
  * the XR camera. If you need the fov on app level, you have to compute in
14725
14490
  * manually from the XR camera's projection matrices.
14726
14491
  *
14492
+ * The camera's transformation and projection matrix are derived from the first
14493
+ * sub camera (e.g. the left eye in a stereo setup).
14494
+ *
14727
14495
  * @return {ArrayCamera} The XR camera.
14728
14496
  */
14729
14497
  this.getCamera = function () {
@@ -15415,6 +15183,19 @@ function WebGLMaterials( renderer, properties ) {
15415
15183
 
15416
15184
  uniforms.ior.value = material.ior; // also part of uniforms common
15417
15185
 
15186
+ if ( material.diffuseRoughness > 0 ) {
15187
+
15188
+ uniforms.diffuseRoughness.value = material.diffuseRoughness;
15189
+
15190
+ if ( material.diffuseRoughnessMap ) {
15191
+
15192
+ uniforms.diffuseRoughnessMap.value = material.diffuseRoughnessMap;
15193
+ refreshTransformUniform( material.diffuseRoughnessMap, uniforms.diffuseRoughnessMapTransform );
15194
+
15195
+ }
15196
+
15197
+ }
15198
+
15418
15199
  if ( material.sheen > 0 ) {
15419
15200
 
15420
15201
  uniforms.sheenColor.value.copy( material.sheenColor ).multiplyScalar( material.sheen );
@@ -15494,8 +15275,8 @@ function WebGLMaterials( renderer, properties ) {
15494
15275
 
15495
15276
  uniforms.iridescence.value = material.iridescence;
15496
15277
  uniforms.iridescenceIOR.value = material.iridescenceIOR;
15497
- uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[ 0 ];
15498
- uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[ 1 ];
15278
+ uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessMinimum;
15279
+ uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessMaximum;
15499
15280
 
15500
15281
  if ( material.iridescenceMap ) {
15501
15282
 
@@ -15610,14 +15391,11 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
15610
15391
 
15611
15392
  let buffers = {};
15612
15393
  let updateList = {};
15613
- let allocatedBindingPoints = [];
15614
-
15615
- const maxBindingPoints = gl.getParameter( gl.MAX_UNIFORM_BUFFER_BINDINGS ); // binding points are global whereas block indices are per shader program
15616
15394
 
15617
15395
  function bind( uniformsGroup, program ) {
15618
15396
 
15619
15397
  const webglProgram = program.program;
15620
- state.uniformBlockBinding( uniformsGroup, webglProgram );
15398
+ state.uniformBlockBinding( uniformsGroup, webglProgram, buffers[ uniformsGroup.id ] );
15621
15399
 
15622
15400
  }
15623
15401
 
@@ -15657,11 +15435,6 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
15657
15435
 
15658
15436
  function createBuffer( uniformsGroup ) {
15659
15437
 
15660
- // the setup of an UBO is independent of a particular shader program but global
15661
-
15662
- const bindingPointIndex = allocateBindingPointIndex();
15663
- uniformsGroup.__bindingPointIndex = bindingPointIndex;
15664
-
15665
15438
  const buffer = gl.createBuffer();
15666
15439
  const size = uniformsGroup.__size;
15667
15440
  const usage = uniformsGroup.usage;
@@ -15669,31 +15442,11 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
15669
15442
  gl.bindBuffer( gl.UNIFORM_BUFFER, buffer );
15670
15443
  gl.bufferData( gl.UNIFORM_BUFFER, size, usage );
15671
15444
  gl.bindBuffer( gl.UNIFORM_BUFFER, null );
15672
- gl.bindBufferBase( gl.UNIFORM_BUFFER, bindingPointIndex, buffer );
15673
15445
 
15674
15446
  return buffer;
15675
15447
 
15676
15448
  }
15677
15449
 
15678
- function allocateBindingPointIndex() {
15679
-
15680
- for ( let i = 0; i < maxBindingPoints; i ++ ) {
15681
-
15682
- if ( allocatedBindingPoints.indexOf( i ) === -1 ) {
15683
-
15684
- allocatedBindingPoints.push( i );
15685
- return i;
15686
-
15687
- }
15688
-
15689
- }
15690
-
15691
- error( 'WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' );
15692
-
15693
- return 0;
15694
-
15695
- }
15696
-
15697
15450
  function updateBufferData( uniformsGroup ) {
15698
15451
 
15699
15452
  const buffer = buffers[ uniformsGroup.id ];
@@ -15740,16 +15493,11 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
15740
15493
  for ( let k = 0; k < value.length; k ++ ) {
15741
15494
 
15742
15495
  const val = value[ k ];
15743
- const info = getUniformSize( val );
15496
+ const info = getUniformSize( val, true );
15744
15497
 
15745
15498
  writeUniformValue( val, uniform.__data, arrayOffset );
15746
15499
 
15747
- // only toArray() values advance arrayOffset
15748
- if ( typeof val !== 'number' && typeof val !== 'boolean' && ! val.isMatrix3 && ! ArrayBuffer.isView( val ) ) {
15749
-
15750
- arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT;
15751
-
15752
- }
15500
+ arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT;
15753
15501
 
15754
15502
  }
15755
15503
 
@@ -15767,32 +15515,32 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
15767
15515
 
15768
15516
  function writeUniformValue( value, data, offset ) {
15769
15517
 
15770
- // TODO add integer and struct support
15518
+ // TODO add integer vector and struct support
15771
15519
  if ( typeof value === 'number' || typeof value === 'boolean' ) {
15772
15520
 
15773
- data[ 0 ] = value;
15521
+ data[ offset ] = value;
15774
15522
 
15775
15523
  } else if ( value.isMatrix3 ) {
15776
15524
 
15777
15525
  // manually converting 3x3 to 3x4
15778
15526
 
15779
- data[ 0 ] = value.elements[ 0 ];
15780
- data[ 1 ] = value.elements[ 1 ];
15781
- data[ 2 ] = value.elements[ 2 ];
15782
- data[ 3 ] = 0;
15783
- data[ 4 ] = value.elements[ 3 ];
15784
- data[ 5 ] = value.elements[ 4 ];
15785
- data[ 6 ] = value.elements[ 5 ];
15786
- data[ 7 ] = 0;
15787
- data[ 8 ] = value.elements[ 6 ];
15788
- data[ 9 ] = value.elements[ 7 ];
15789
- data[ 10 ] = value.elements[ 8 ];
15790
- data[ 11 ] = 0;
15527
+ data[ offset ] = value.elements[ 0 ];
15528
+ data[ offset + 1 ] = value.elements[ 1 ];
15529
+ data[ offset + 2 ] = value.elements[ 2 ];
15530
+ data[ offset + 3 ] = 0;
15531
+ data[ offset + 4 ] = value.elements[ 3 ];
15532
+ data[ offset + 5 ] = value.elements[ 4 ];
15533
+ data[ offset + 6 ] = value.elements[ 5 ];
15534
+ data[ offset + 7 ] = 0;
15535
+ data[ offset + 8 ] = value.elements[ 6 ];
15536
+ data[ offset + 9 ] = value.elements[ 7 ];
15537
+ data[ offset + 10 ] = value.elements[ 8 ];
15538
+ data[ offset + 11 ] = 0;
15791
15539
 
15792
15540
  } else if ( ArrayBuffer.isView( value ) ) {
15793
15541
 
15794
15542
  // copy the buffer data using "set"
15795
- data.set( new value.constructor( value.buffer, value.byteOffset, data.length ) );
15543
+ data.set( value.subarray( 0, data.length - offset ), offset );
15796
15544
 
15797
15545
  } else {
15798
15546
 
@@ -15807,21 +15555,47 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
15807
15555
  const value = uniform.value;
15808
15556
  const indexString = index + '_' + indexArray;
15809
15557
 
15810
- if ( cache[ indexString ] === undefined ) {
15558
+ if ( Array.isArray( value ) ) {
15559
+
15560
+ // arrays are cached per element
15561
+
15562
+ if ( cache[ indexString ] === undefined ) cache[ indexString ] = [];
15563
+
15564
+ const cachedArray = cache[ indexString ];
15565
+
15566
+ let changed = false;
15567
+
15568
+ for ( let k = 0; k < value.length; k ++ ) {
15569
+
15570
+ if ( hasValueChanged( value[ k ], cachedArray, k ) === true ) changed = true;
15571
+
15572
+ }
15573
+
15574
+ return changed;
15575
+
15576
+ }
15577
+
15578
+ return hasValueChanged( value, cache, indexString );
15579
+
15580
+ }
15581
+
15582
+ function hasValueChanged( value, cache, key ) {
15583
+
15584
+ if ( cache[ key ] === undefined ) {
15811
15585
 
15812
15586
  // cache entry does not exist so far
15813
15587
 
15814
15588
  if ( typeof value === 'number' || typeof value === 'boolean' ) {
15815
15589
 
15816
- cache[ indexString ] = value;
15590
+ cache[ key ] = value;
15817
15591
 
15818
15592
  } else if ( ArrayBuffer.isView( value ) ) {
15819
15593
 
15820
- cache[ indexString ] = value.slice();
15594
+ cache[ key ] = value.slice();
15821
15595
 
15822
15596
  } else {
15823
15597
 
15824
- cache[ indexString ] = value.clone();
15598
+ cache[ key ] = value.clone();
15825
15599
 
15826
15600
  }
15827
15601
 
@@ -15829,7 +15603,7 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
15829
15603
 
15830
15604
  } else {
15831
15605
 
15832
- const cachedObject = cache[ indexString ];
15606
+ const cachedObject = cache[ key ];
15833
15607
 
15834
15608
  // compare current value with cached entry
15835
15609
 
@@ -15837,7 +15611,7 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
15837
15611
 
15838
15612
  if ( cachedObject !== value ) {
15839
15613
 
15840
- cache[ indexString ] = value;
15614
+ cache[ key ] = value;
15841
15615
  return true;
15842
15616
 
15843
15617
  }
@@ -15884,11 +15658,16 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
15884
15658
 
15885
15659
  const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ];
15886
15660
 
15661
+ // arrays of uniforms and uniforms with array values both represent GLSL arrays
15662
+ const isArray = Array.isArray( uniforms[ i ] ) || Array.isArray( uniform.value );
15663
+
15664
+ let start = offset;
15665
+
15887
15666
  for ( let k = 0, kl = values.length; k < kl; k ++ ) {
15888
15667
 
15889
15668
  const value = values[ k ];
15890
15669
 
15891
- const info = getUniformSize( value );
15670
+ const info = getUniformSize( value, isArray );
15892
15671
 
15893
15672
  const chunkOffset = offset % chunkSize; // offset in the current chunk
15894
15673
  const chunkPadding = chunkOffset % info.boundary; // required padding to match boundary
@@ -15904,15 +15683,18 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
15904
15683
 
15905
15684
  }
15906
15685
 
15907
- // the following two properties will be used for partial buffer updates
15908
- uniform.__data = new Float32Array( info.storage / Float32Array.BYTES_PER_ELEMENT );
15909
- uniform.__offset = offset;
15686
+ if ( k === 0 ) start = offset;
15910
15687
 
15911
15688
  // Update the global offset
15912
15689
  offset += info.storage;
15913
15690
 
15914
15691
  }
15915
15692
 
15693
+ // the following two properties will be used for partial buffer updates
15694
+ const ArrayType = uniform.type === 'int' ? Int32Array : uniform.type === 'uint' ? Uint32Array : Float32Array;
15695
+ uniform.__data = new ArrayType( ( offset - start ) / Float32Array.BYTES_PER_ELEMENT );
15696
+ uniform.__offset = start;
15697
+
15916
15698
  }
15917
15699
 
15918
15700
  }
@@ -15932,7 +15714,7 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
15932
15714
 
15933
15715
  }
15934
15716
 
15935
- function getUniformSize( value ) {
15717
+ function getUniformSize( value, isArrayElement ) {
15936
15718
 
15937
15719
  const info = {
15938
15720
  boundary: 0, // bytes
@@ -15973,14 +15755,14 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
15973
15755
 
15974
15756
  // mat3 (in STD140 a 3x3 matrix is represented as 3x4)
15975
15757
 
15976
- info.boundary = 48;
15758
+ info.boundary = 16;
15977
15759
  info.storage = 48;
15978
15760
 
15979
15761
  } else if ( value.isMatrix4 ) {
15980
15762
 
15981
15763
  // mat4
15982
15764
 
15983
- info.boundary = 64;
15765
+ info.boundary = 16;
15984
15766
  info.storage = 64;
15985
15767
 
15986
15768
  } else if ( value.isTexture ) {
@@ -15998,6 +15780,15 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
15998
15780
 
15999
15781
  }
16000
15782
 
15783
+ if ( isArrayElement === true ) {
15784
+
15785
+ // the alignment and stride of array elements are rounded up to the size of a vec4
15786
+
15787
+ info.boundary = 16;
15788
+ info.storage = Math.ceil( info.storage / 16 ) * 16;
15789
+
15790
+ }
15791
+
16001
15792
  return info;
16002
15793
 
16003
15794
  }
@@ -16008,9 +15799,6 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
16008
15799
 
16009
15800
  uniformsGroup.removeEventListener( 'dispose', onUniformsGroupsDispose );
16010
15801
 
16011
- const index = allocatedBindingPoints.indexOf( uniformsGroup.__bindingPointIndex );
16012
- allocatedBindingPoints.splice( index, 1 );
16013
-
16014
15802
  gl.deleteBuffer( buffers[ uniformsGroup.id ] );
16015
15803
 
16016
15804
  delete buffers[ uniformsGroup.id ];
@@ -16026,7 +15814,6 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
16026
15814
 
16027
15815
  }
16028
15816
 
16029
- allocatedBindingPoints = [];
16030
15817
  buffers = {};
16031
15818
  updateList = {};
16032
15819
 
@@ -16167,7 +15954,7 @@ class WebGLRenderer {
16167
15954
 
16168
15955
  const uintClearColor = new Uint32Array( 4 );
16169
15956
  const intClearColor = new Int32Array( 4 );
16170
- const objectPosition = new Vector3();
15957
+ const lightProbeGridUniforms = { textures: [], min: [], max: [], resolution: [] };
16171
15958
 
16172
15959
  let currentRenderList = null;
16173
15960
  let currentRenderState = null;
@@ -16378,6 +16165,7 @@ class WebGLRenderer {
16378
16165
  // frustum
16379
16166
 
16380
16167
  const _frustum = new Frustum();
16168
+ const _frustumArray = new FrustumArray();
16381
16169
 
16382
16170
  // clipping
16383
16171
 
@@ -16854,7 +16642,7 @@ class WebGLRenderer {
16854
16642
 
16855
16643
  }
16856
16644
 
16857
- state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).round() );
16645
+ state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( getTargetPixelRatio() ).round() );
16858
16646
 
16859
16647
  };
16860
16648
 
@@ -16891,7 +16679,7 @@ class WebGLRenderer {
16891
16679
 
16892
16680
  }
16893
16681
 
16894
- state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).round() );
16682
+ state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( getTargetPixelRatio() ).round() );
16895
16683
 
16896
16684
  };
16897
16685
 
@@ -17129,9 +16917,11 @@ class WebGLRenderer {
17129
16917
  background.dispose();
17130
16918
  renderLists.dispose();
17131
16919
  renderStates.dispose();
16920
+ textures.dispose();
17132
16921
  properties.dispose();
17133
16922
  environments.dispose();
17134
16923
  objects.dispose();
16924
+ geometries.dispose();
17135
16925
  bindingStates.dispose();
17136
16926
  uniformsGroups.dispose();
17137
16927
  programCache.dispose();
@@ -17721,7 +17511,16 @@ class WebGLRenderer {
17721
17511
  renderStateStack.push( currentRenderState );
17722
17512
 
17723
17513
  _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
17724
- _frustum.setFromProjectionMatrix( _projScreenMatrix, WebGLCoordinateSystem, camera.reversedDepth );
17514
+
17515
+ if ( camera.isArrayCamera ) {
17516
+
17517
+ _frustumArray.setFromArrayCamera( camera );
17518
+
17519
+ } else {
17520
+
17521
+ _frustum.setFromProjectionMatrix( _projScreenMatrix, WebGLCoordinateSystem, camera.reversedDepth );
17522
+
17523
+ }
17725
17524
 
17726
17525
  _localClippingEnabled = this.localClippingEnabled;
17727
17526
  _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled );
@@ -17731,6 +17530,8 @@ class WebGLRenderer {
17731
17530
 
17732
17531
  renderListStack.push( currentRenderList );
17733
17532
 
17533
+ this.info.render.frame ++; // increment before projectObject(), see #35099
17534
+
17734
17535
  if ( xr.enabled === true && xr.isPresenting === true ) {
17735
17536
 
17736
17537
  const depthSensingMesh = _this.xr.getDepthSensingMesh();
@@ -17763,8 +17564,6 @@ class WebGLRenderer {
17763
17564
 
17764
17565
  //
17765
17566
 
17766
- this.info.render.frame ++;
17767
-
17768
17567
  if ( this.info.autoReset === true ) this.info.reset();
17769
17568
 
17770
17569
  if ( _clippingEnabled === true ) clipping.beginShadows();
@@ -17910,10 +17709,6 @@ class WebGLRenderer {
17910
17709
 
17911
17710
  if ( object.autoUpdate === true ) object.update( camera );
17912
17711
 
17913
- } else if ( object.isLightProbeGrid ) {
17914
-
17915
- currentRenderState.pushLightProbeGrid( object );
17916
-
17917
17712
  } else if ( object.isLight ) {
17918
17713
 
17919
17714
  currentRenderState.pushLight( object );
@@ -17926,7 +17721,9 @@ class WebGLRenderer {
17926
17721
 
17927
17722
  } else if ( object.isSprite ) {
17928
17723
 
17929
- if ( ! object.frustumCulled || object.intersectsFrustum( _frustum ) ) {
17724
+ const frustum = camera.isArrayCamera ? _frustumArray : _frustum;
17725
+
17726
+ if ( ! object.frustumCulled || object.intersectsFrustum( frustum ) ) {
17930
17727
 
17931
17728
  if ( sortObjects ) {
17932
17729
 
@@ -17948,7 +17745,9 @@ class WebGLRenderer {
17948
17745
 
17949
17746
  } else if ( object.isMesh || object.isLine || object.isPoints ) {
17950
17747
 
17951
- if ( ! object.frustumCulled || object.intersectsFrustum( _frustum ) ) {
17748
+ const frustum = camera.isArrayCamera ? _frustumArray : _frustum;
17749
+
17750
+ if ( ! object.frustumCulled || object.intersectsFrustum( frustum ) ) {
17952
17751
 
17953
17752
  const geometry = objects.update( object );
17954
17753
  const material = object.material;
@@ -18221,6 +18020,16 @@ class WebGLRenderer {
18221
18020
 
18222
18021
  }
18223
18022
 
18023
+ function countLightProbeGrids( grids ) {
18024
+
18025
+ let count = 0;
18026
+
18027
+ for ( const grid of grids ) if ( grid.texture !== null ) count ++;
18028
+
18029
+ return count;
18030
+
18031
+ }
18032
+
18224
18033
  function getProgram( material, scene, object ) {
18225
18034
 
18226
18035
  if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
@@ -18254,6 +18063,7 @@ class WebGLRenderer {
18254
18063
 
18255
18064
  programs = new Map();
18256
18065
  materialProperties.programs = programs;
18066
+ materialProperties.programVariants = new Map();
18257
18067
 
18258
18068
  }
18259
18069
 
@@ -18335,7 +18145,7 @@ class WebGLRenderer {
18335
18145
 
18336
18146
  }
18337
18147
 
18338
- materialProperties.lightProbeGrid = currentRenderState.state.lightProbeGridArray.length > 0;
18148
+ materialProperties.numLightProbeGrids = countLightProbeGrids( currentRenderState.state.lightProbeGridArray );
18339
18149
 
18340
18150
  materialProperties.currentProgram = program;
18341
18151
  materialProperties.uniformsList = null;
@@ -18344,6 +18154,33 @@ class WebGLRenderer {
18344
18154
 
18345
18155
  }
18346
18156
 
18157
+ function getProgramVariant( material, scene, object, colorSpace, toneMapping ) {
18158
+
18159
+ const materialProperties = properties.get( material );
18160
+
18161
+ const programVariantKey = materialProperties.currentProgram.id + ',' + colorSpace + ',' + toneMapping;
18162
+
18163
+ let program = materialProperties.programVariants.get( programVariantKey );
18164
+
18165
+ if ( program === undefined ) {
18166
+
18167
+ program = getProgram( material, scene, object );
18168
+
18169
+ materialProperties.programVariants.set( programVariantKey, program );
18170
+
18171
+ } else {
18172
+
18173
+ materialProperties.currentProgram = program;
18174
+ materialProperties.uniformsList = null;
18175
+ materialProperties.outputColorSpace = colorSpace;
18176
+ materialProperties.toneMapping = toneMapping;
18177
+
18178
+ }
18179
+
18180
+ return program;
18181
+
18182
+ }
18183
+
18347
18184
  function getUniformList( materialProperties ) {
18348
18185
 
18349
18186
  if ( materialProperties.uniformsList === null ) {
@@ -18380,30 +18217,6 @@ class WebGLRenderer {
18380
18217
 
18381
18218
  }
18382
18219
 
18383
- function findLightProbeGrid( volumes, object ) {
18384
-
18385
- if ( volumes.length === 0 ) return null;
18386
-
18387
- if ( volumes.length === 1 ) {
18388
-
18389
- return volumes[ 0 ].texture !== null ? volumes[ 0 ] : null;
18390
-
18391
- }
18392
-
18393
- objectPosition.setFromMatrixPosition( object.matrixWorld );
18394
-
18395
- for ( let i = 0, l = volumes.length; i < l; i ++ ) {
18396
-
18397
- const v = volumes[ i ];
18398
-
18399
- if ( v.texture !== null && v.boundingBox.containsPoint( objectPosition ) ) return v;
18400
-
18401
- }
18402
-
18403
- return null;
18404
-
18405
- }
18406
-
18407
18220
  function setProgram( camera, scene, geometry, material, object ) {
18408
18221
 
18409
18222
  if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
@@ -18459,6 +18272,7 @@ class WebGLRenderer {
18459
18272
  //
18460
18273
 
18461
18274
  let needsProgramChange = false;
18275
+ let needsProgramVariant = false;
18462
18276
 
18463
18277
  if ( material.version === materialProperties.__version ) {
18464
18278
 
@@ -18466,10 +18280,6 @@ class WebGLRenderer {
18466
18280
 
18467
18281
  needsProgramChange = true;
18468
18282
 
18469
- } else if ( materialProperties.outputColorSpace !== colorSpace ) {
18470
-
18471
- needsProgramChange = true;
18472
-
18473
18283
  } else if ( object.isBatchedMesh && materialProperties.batching === false ) {
18474
18284
 
18475
18285
  needsProgramChange = true;
@@ -18552,17 +18362,17 @@ class WebGLRenderer {
18552
18362
 
18553
18363
  needsProgramChange = true;
18554
18364
 
18555
- } else if ( materialProperties.toneMapping !== toneMapping ) {
18365
+ } else if ( materialProperties.morphTargetsCount !== morphTargetsCount ) {
18556
18366
 
18557
18367
  needsProgramChange = true;
18558
18368
 
18559
- } else if ( materialProperties.morphTargetsCount !== morphTargetsCount ) {
18369
+ } else if ( materialProperties.numLightProbeGrids !== countLightProbeGrids( currentRenderState.state.lightProbeGridArray ) ) {
18560
18370
 
18561
18371
  needsProgramChange = true;
18562
18372
 
18563
- } else if ( !! materialProperties.lightProbeGrid !== ( currentRenderState.state.lightProbeGridArray.length > 0 ) ) {
18373
+ } else if ( materialProperties.outputColorSpace !== colorSpace || materialProperties.toneMapping !== toneMapping ) {
18564
18374
 
18565
- needsProgramChange = true;
18375
+ needsProgramVariant = true;
18566
18376
 
18567
18377
  }
18568
18378
 
@@ -18577,9 +18387,9 @@ class WebGLRenderer {
18577
18387
 
18578
18388
  let program = materialProperties.currentProgram;
18579
18389
 
18580
- if ( needsProgramChange === true ) {
18390
+ if ( needsProgramChange === true || needsProgramVariant === true ) {
18581
18391
 
18582
- program = getProgram( material, scene, object );
18392
+ program = ( needsProgramVariant === true ) ? getProgramVariant( material, scene, object, colorSpace, toneMapping ) : getProgram( material, scene, object );
18583
18393
 
18584
18394
  // notify the node builder that the program has changed so uniforms and update nodes can
18585
18395
  // be cached and triggered.
@@ -18614,19 +18424,6 @@ class WebGLRenderer {
18614
18424
 
18615
18425
  }
18616
18426
 
18617
- if ( materialProperties.needsLights ) {
18618
-
18619
- const objectVolume = findLightProbeGrid( currentRenderState.state.lightProbeGridArray, object );
18620
-
18621
- if ( materialProperties.lightProbeGrid !== objectVolume ) {
18622
-
18623
- materialProperties.lightProbeGrid = objectVolume;
18624
- refreshMaterial = true;
18625
-
18626
- }
18627
-
18628
- }
18629
-
18630
18427
  if ( refreshProgram || _currentCamera !== camera ) {
18631
18428
 
18632
18429
  // common camera uniforms
@@ -18814,14 +18611,29 @@ class WebGLRenderer {
18814
18611
 
18815
18612
  // light probe volume
18816
18613
 
18817
- if ( materialProperties.needsLights && materialProperties.lightProbeGrid ) {
18614
+ if ( materialProperties.needsLights && materialProperties.numLightProbeGrids > 0 ) {
18818
18615
 
18819
- const volume = materialProperties.lightProbeGrid;
18616
+ const grids = lightProbeGridUniforms;
18617
+ let count = 0;
18820
18618
 
18821
- m_uniforms.probesSH.value = volume.texture;
18822
- m_uniforms.probesMin.value.copy( volume.boundingBox.min );
18823
- m_uniforms.probesMax.value.copy( volume.boundingBox.max );
18824
- m_uniforms.probesResolution.value.copy( volume.resolution );
18619
+ for ( const grid of currentRenderState.state.lightProbeGridArray ) {
18620
+
18621
+ if ( grid.texture === null ) continue;
18622
+
18623
+ grids.textures[ count ] = grid.texture;
18624
+ grids.min[ count ] = grid.boundingBox.min;
18625
+ grids.max[ count ] = grid.boundingBox.max;
18626
+ grids.resolution[ count ] = grid.resolution;
18627
+ count ++;
18628
+
18629
+ }
18630
+
18631
+ for ( const key in grids ) grids[ key ].length = count;
18632
+
18633
+ m_uniforms.probesSH.value = grids.textures;
18634
+ m_uniforms.probesMin.value = grids.min;
18635
+ m_uniforms.probesMax.value = grids.max;
18636
+ m_uniforms.probesResolution.value = grids.resolution;
18825
18637
 
18826
18638
  }
18827
18639
 
@@ -19181,6 +18993,9 @@ class WebGLRenderer {
19181
18993
 
19182
18994
  framebuffer = framebuffer[ activeCubeFaceIndex ];
19183
18995
 
18996
+ // Custom mip chains store one framebuffer per level; read level 0.
18997
+ if ( Array.isArray( framebuffer ) ) framebuffer = framebuffer[ 0 ];
18998
+
19184
18999
  }
19185
19000
 
19186
19001
  if ( framebuffer ) {
@@ -19263,6 +19078,9 @@ class WebGLRenderer {
19263
19078
 
19264
19079
  framebuffer = framebuffer[ activeCubeFaceIndex ];
19265
19080
 
19081
+ // Custom mip chains store one framebuffer per level; read level 0.
19082
+ if ( Array.isArray( framebuffer ) ) framebuffer = framebuffer[ 0 ];
19083
+
19266
19084
  }
19267
19085
 
19268
19086
  if ( framebuffer ) {
@@ -19487,7 +19305,7 @@ class WebGLRenderer {
19487
19305
 
19488
19306
  }
19489
19307
 
19490
- _gl.blitFramebuffer( minX, minY, width, height, dstX, dstY, width, height, _gl.DEPTH_BUFFER_BIT, _gl.NEAREST );
19308
+ _gl.blitFramebuffer( minX, minY, minX + width, minY + height, dstX, dstY, dstX + width, dstY + height, _gl.DEPTH_BUFFER_BIT, _gl.NEAREST );
19491
19309
 
19492
19310
  }
19493
19311
 
@@ -19530,7 +19348,7 @@ class WebGLRenderer {
19530
19348
  // copy the data using the fastest function that can achieve the copy
19531
19349
  if ( srcLevel !== 0 ) {
19532
19350
 
19533
- _gl.blitFramebuffer( minX, minY, width, height, dstX, dstY, width, height, _gl.COLOR_BUFFER_BIT, _gl.NEAREST );
19351
+ _gl.blitFramebuffer( minX, minY, minX + width, minY + height, dstX, dstY, dstX + width, dstY + height, _gl.COLOR_BUFFER_BIT, _gl.NEAREST );
19534
19352
 
19535
19353
  } else if ( isDst3D ) {
19536
19354
 
@@ -19596,7 +19414,7 @@ class WebGLRenderer {
19596
19414
  state.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages );
19597
19415
 
19598
19416
  // Generate mipmaps only when copying level 0
19599
- if ( dstLevel === 0 && dstTexture.generateMipmaps ) {
19417
+ if ( dstLevel === 0 && dstTexture.generateMipmaps === true && dstTexture.mipmapsAutoUpdate === true ) {
19600
19418
 
19601
19419
  _gl.generateMipmap( glTarget );
19602
19420
 
@@ -19716,4 +19534,4 @@ class WebGLRenderer {
19716
19534
 
19717
19535
  }
19718
19536
 
19719
- export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveBlending, AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, ArrayCamera, BackSide, BoxGeometry, BufferAttribute, BufferGeometry, ByteType, CineonToneMapping, ClampToEdgeWrapping, Color, ColorManagement, ConstantAlphaFactor, ConstantColorFactor, CubeCamera, CubeDepthTexture, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeUVReflectionMapping, CullFaceBack, CullFaceFront, CullFaceNone, CustomBlending, CustomToneMapping, Data3DTexture, DataArrayTexture, DataTexture, DepthFormat, DepthStencilFormat, DepthTexture, DoubleSide, DstAlphaFactor, DstColorFactor, EqualCompare, EqualDepth, EquirectangularReflectionMapping, EquirectangularRefractionMapping, EventDispatcher, ExternalTexture, Float32BufferAttribute, FloatType, FrontSide, Frustum, GLSL3, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, HalfFloatType, IntType, Layers, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, LinearTransfer, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeutralToneMapping, NeverCompare, NeverDepth, NoBlending, NoColorSpace, NoToneMapping, NormalBlending, NotEqualCompare, NotEqualDepth, ObjectSpaceNormalMap, OneFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, PerspectiveCamera, Plane, PlaneGeometry, R11_EAC_Format, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RG11_EAC_Format, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RawShaderMaterial, RedFormat, RedIntegerFormat, ReinhardToneMapping, RepeatWrapping, ReverseSubtractEquation, SIGNED_R11_EAC_Format, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SIGNED_RG11_EAC_Format, SRGBColorSpace, SRGBTransfer, ShaderChunk, ShaderLib, ShaderMaterial, ShortType, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, SubtractEquation, SubtractiveBlending, TangentSpaceNormalMap, Texture, Uint16BufferAttribute, Uint32BufferAttribute, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt101111Type, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGLRenderTarget, WebGLRenderer, WebGLUtils, WebXRController, ZeroFactor, createCanvasElement, error, log, warn, warnOnce };
19537
+ export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveBlending, AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, ArrayCamera, BackSide, BoxGeometry, BufferAttribute, BufferGeometry, ByteType, CineonToneMapping, ClampToEdgeWrapping, Color, ColorManagement, ConstantAlphaFactor, ConstantColorFactor, CubeCamera, CubeDepthTexture, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CullFaceBack, CullFaceFront, CullFaceNone, CustomBlending, CustomToneMapping, Data3DTexture, DataArrayTexture, DataTexture, DepthFormat, DepthStencilFormat, DepthTexture, DoubleSide, DstAlphaFactor, DstColorFactor, EqualCompare, EqualDepth, EquirectangularReflectionMapping, EquirectangularRefractionMapping, EventDispatcher, ExternalTexture, Float32BufferAttribute, FloatType, FrontSide, Frustum, FrustumArray, GLSL3, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, HalfFloatType, IntType, Layers, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, LinearTransfer, Matrix3, Matrix4, MaxEquation, Mesh, MeshDepthMaterial, MeshDistanceMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeutralToneMapping, NeverCompare, NeverDepth, NoBlending, NoColorSpace, NoToneMapping, NormalBlending, NotEqualCompare, NotEqualDepth, ObjectSpaceNormalMap, OneFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, PerspectiveCamera, Plane, PlaneGeometry, R11_EAC_Format, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RG11_EAC_Format, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RawShaderMaterial, RedFormat, RedIntegerFormat, ReinhardToneMapping, RepeatWrapping, ReverseSubtractEquation, SIGNED_R11_EAC_Format, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SIGNED_RG11_EAC_Format, SRGBColorSpace, SRGBTransfer, ShaderChunk, ShaderLib, ShaderMaterial, ShortType, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, SubtractEquation, SubtractiveBlending, TangentSpaceNormalMap, Texture, Uint16BufferAttribute, Uint32BufferAttribute, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt101111Type, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGLRenderTarget, WebGLRenderer, WebGLUtils, WebXRController, ZeroFactor, createCanvasElement, error, log, warn, warnOnce };