Mr.doob 1 년 전
부모
커밋
2a20741396
100개의 변경된 파일39493개의 추가작업 그리고 74549개의 파일을 삭제
  1. 582 579
      build/three.cjs
  2. 36986 0
      build/three.core.js
  3. 5 0
      build/three.core.min.js
  4. 0 211
      build/three.module.js
  5. 0 0
      build/three.module.min.js
  6. 532 0
      build/three.tsl.js
  7. 5 0
      build/three.tsl.min.js
  8. 0 36726
      build/three.webgpu.js
  9. 0 0
      build/three.webgpu.min.js
  10. 0 36726
      build/three.webgpu.nodes.js
  11. 0 0
      build/three.webgpu.nodes.min.js
  12. 15 17
      docs/api/ar/core/Clock.html
  13. 12 12
      docs/api/en/constants/Renderer.html
  14. 1 3
      docs/api/en/core/Clock.html
  15. 5 5
      docs/api/en/objects/BatchedMesh.html
  16. 62 0
      docs/api/en/objects/ClippingGroup.html
  17. 6 1
      docs/api/en/renderers/WebGLRenderer.html
  18. 1 2
      docs/api/it/core/Clock.html
  19. 1 1
      docs/api/ko/core/Clock.html
  20. 1 2
      docs/api/zh/core/Clock.html
  21. 5 0
      docs/api/zh/renderers/WebGLRenderer.html
  22. 5 0
      docs/examples/en/controls/ArcballControls.html
  23. 2 0
      docs/examples/en/exporters/GLTFExporter.html
  24. 6 0
      docs/examples/en/lines/LineGeometry.html
  25. 1 1
      docs/examples/en/loaders/MMDLoader.html
  26. 1 1
      docs/examples/en/loaders/OBJLoader.html
  27. 1 1
      docs/examples/en/loaders/PCDLoader.html
  28. 1 1
      docs/examples/en/loaders/PDBLoader.html
  29. 1 1
      docs/examples/en/loaders/SVGLoader.html
  30. 1 1
      docs/examples/en/loaders/TGALoader.html
  31. 5 0
      docs/examples/ko/controls/ArcballControls.html
  32. 5 0
      docs/examples/zh/controls/ArcballControls.html
  33. 2 0
      docs/examples/zh/exporters/GLTFExporter.html
  34. 1 1
      docs/examples/zh/loaders/MMDLoader.html
  35. 1 1
      docs/examples/zh/loaders/OBJLoader.html
  36. 1 1
      docs/examples/zh/loaders/PCDLoader.html
  37. 1 1
      docs/examples/zh/loaders/PDBLoader.html
  38. 1 1
      docs/examples/zh/loaders/SVGLoader.html
  39. 1 1
      docs/examples/zh/loaders/TGALoader.html
  40. 4 1
      docs/list.json
  41. 2 3
      docs/manual/fr/introduction/How-to-use-post-processing.html
  42. 265 0
      docs/manual/ko/introduction/Color-management.html
  43. 117 0
      docs/manual/ko/introduction/Libraries-and-Plugins.html
  44. 2 0
      examples/files.json
  45. 5 5
      examples/index.html
  46. 1 10
      examples/jsm/capabilities/WebGPU.js
  47. 25 21
      examples/jsm/controls/ArcballControls.js
  48. 41 9
      examples/jsm/controls/OrbitControls.js
  49. 2 5
      examples/jsm/controls/PointerLockControls.js
  50. 7 5
      examples/jsm/csm/CSMShadowNode.js
  51. 5 1
      examples/jsm/geometries/DecalGeometry.js
  52. 1 1
      examples/jsm/lighting/TiledLighting.js
  53. 25 0
      examples/jsm/lines/LineGeometry.js
  54. 1 7
      examples/jsm/lines/LineMaterial.js
  55. 2 1
      examples/jsm/lines/webgpu/Line2.js
  56. 2 1
      examples/jsm/lines/webgpu/LineSegments2.js
  57. 2 1
      examples/jsm/lines/webgpu/Wireframe.js
  58. 3 0
      examples/jsm/loaders/KTX2Loader.js
  59. 2 6
      examples/jsm/loaders/MMDLoader.js
  60. 2 2
      examples/jsm/loaders/MaterialXLoader.js
  61. 2 6
      examples/jsm/materials/MeshGouraudMaterial.js
  62. 2 2
      examples/jsm/misc/ProgressiveLightMapGPU.js
  63. 2 4
      examples/jsm/objects/InstancedPoints.js
  64. 4 2
      examples/jsm/objects/LensflareMesh.js
  65. 5 3
      examples/jsm/objects/SkyMesh.js
  66. 7 3
      examples/jsm/objects/Water2Mesh.js
  67. 5 3
      examples/jsm/objects/WaterMesh.js
  68. 2 2
      examples/jsm/transpiler/AST.js
  69. 57 25
      examples/jsm/transpiler/GLSLDecoder.js
  70. 11 6
      examples/jsm/transpiler/TSLEncoder.js
  71. 3 3
      examples/jsm/tsl/display/AfterImageNode.js
  72. 2 2
      examples/jsm/tsl/display/AnaglyphPassNode.js
  73. 2 2
      examples/jsm/tsl/display/AnamorphicNode.js
  74. 3 3
      examples/jsm/tsl/display/BloomNode.js
  75. 48 12
      examples/jsm/tsl/display/DenoiseNode.js
  76. 3 2
      examples/jsm/tsl/display/DepthOfFieldNode.js
  77. 2 2
      examples/jsm/tsl/display/DotScreenNode.js
  78. 3 3
      examples/jsm/tsl/display/FXAANode.js
  79. 3 2
      examples/jsm/tsl/display/FilmNode.js
  80. 62 27
      examples/jsm/tsl/display/GTAONode.js
  81. 6 8
      examples/jsm/tsl/display/GaussianBlurNode.js
  82. 3 3
      examples/jsm/tsl/display/LensflareNode.js
  83. 3 2
      examples/jsm/tsl/display/Lut3DNode.js
  84. 2 2
      examples/jsm/tsl/display/OutlineNode.js
  85. 2 1
      examples/jsm/tsl/display/ParallaxBarrierPassNode.js
  86. 4 4
      examples/jsm/tsl/display/PixelationPassNode.js
  87. 2 1
      examples/jsm/tsl/display/RGBShiftNode.js
  88. 3 3
      examples/jsm/tsl/display/SMAANode.js
  89. 2 2
      examples/jsm/tsl/display/SSAAPassNode.js
  90. 31 8
      examples/jsm/tsl/display/SSRNode.js
  91. 3 3
      examples/jsm/tsl/display/SobelOperatorNode.js
  92. 4 4
      examples/jsm/tsl/display/StereoCompositePassNode.js
  93. 2 2
      examples/jsm/tsl/display/StereoPassNode.js
  94. 2 2
      examples/jsm/tsl/display/TRAAPassNode.js
  95. 3 2
      examples/jsm/tsl/display/TransitionNode.js
  96. 6 9
      examples/jsm/tsl/lighting/TiledLightsNode.js
  97. 410 0
      examples/jsm/utils/SceneOptimizer.js
  98. 1 1
      examples/jsm/utils/UVsDebug.js
  99. 1 0
      examples/misc_controls_arcball.html
  100. 3 2
      examples/misc_controls_fly.html

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 582 - 579
build/three.cjs


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 36986 - 0
build/three.core.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 5 - 0
build/three.core.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 211
build/three.module.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
build/three.module.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 532 - 0
build/three.tsl.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 5 - 0
build/three.tsl.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 36726
build/three.webgpu.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
build/three.webgpu.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 36726
build/three.webgpu.nodes.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
build/three.webgpu.nodes.min.js


+ 15 - 17
docs/api/ar/core/Clock.html

@@ -8,66 +8,64 @@
 	</head>
 	<body class="rtl">
 		<h1>[name]</h1>
-	 
+
 		<p class="desc">
 		كائن لتتبع الوقت. يستخدم هذا
-		[link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now] إذا كان متاحًا، وإلا فإنه يعود إلى
-		دقة أقل
-		[link:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/now Date.now].
+		[link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now].
 		</p>
-	 
+
 		<h2>المنشئ (Constructor)</h2>
-	 
+
 		<h3>[name]( [param:Boolean autoStart] )</h3>
 		<p>
 		autoStart — (اختياري) ما إذا كان يجب تشغيل الساعة تلقائيًا عندما
 		[page:.getDelta]() يتم استدعاؤه لأول مرة. الافتراضي هو `true`.
 		</p>
-	 
+
 		<h2>الخصائص (Properties)</h2>
-	 
+
 		<h3>[property:Boolean autoStart]</h3>
 		<p>
 		إذا تم تعيينه، يبدأ الساعة تلقائيًا عندما يتم استدعاء [page:.getDelta]()
 		لأول مرة. الافتراضي هو `true`.
 		</p>
-	 
+
 		<h3>[property:Float startTime]</h3>
 		<p>
 		يحمل الوقت الذي تم فيه استدعاء طريقة [page:Clock.start start] للساعة
 		آخر مرة. الافتراضي هو `0`.
 		</p>
-	 
+
 		<h3>[property:Float oldTime]</h3>
 		<p>
 		يحمل الوقت الذي تم فيه استدعاء طرق [page:Clock.start start],
 		[page:.getElapsedTime]() أو [page:.getDelta]() للساعة آخر مرة.
 		الافتراضي هو `0`.
 		</p>
-	 
+
 		<h3>[property:Float elapsedTime]</h3>
 		<p>
 		يتبع المجموع الكلي للوقت الذي كانت تعمل فيه الساعة. الافتراضي هو
 		`0`.
 		</p>
-	 
+
 		<h3>[property:Boolean running]</h3>
 		<p>ما إذا كانت الساعة تعمل أم لا. الافتراضي هو `false`.</p>
-	 
+
 		<h2>الوظائف (Methods)</h2>
-	 
+
 		<h3>[method:undefined start]()</h3>
 		<p>
 		يبدأ الساعة. كما يضبط [page:.startTime] و [page:.oldTime] على
 		الوقت الحالي، ويضبط [page:.elapsedTime] على `0` و [page:.running] على
 		`true`.
 		</p>
-	 
+
 		<h3>[method:undefined stop]()</h3>
 		<p>
 		يوقف الساعة ويضبط [page:Clock.oldTime oldTime] على الوقت الحالي.
 		</p>
-	 
+
 		<h3>[method:Float getElapsedTime]()</h3>
 		<p>
 		احصل على المجموع الكلي للثواني التي مرت منذ بدء تشغيل الساعة وضبط [page:.oldTime] على
@@ -75,7 +73,7 @@
 		إذا كان [page:.autoStart] هو `true` والساعة لا تعمل، فإنه يبدأ أيضًا
 		ساعة.
 		</p>
-	 
+
 		<h3>[method:Float getDelta]()</h3>
 		<p>
 		احصل على المجموع الكلي للثواني التي مرت منذ ضبط [page:.oldTime] وضبط

+ 12 - 12
docs/api/en/constants/Renderer.html

@@ -11,8 +11,8 @@
 
 		<h2>Cull Face Modes</h2>
 		<code>
-		THREE.CullFaceNone 
-		THREE.CullFaceBack 
+		THREE.CullFaceNone
+		THREE.CullFaceBack
 		THREE.CullFaceFront
 		THREE.CullFaceFrontBack
 		</code>
@@ -25,14 +25,14 @@
 
 		<h2>Shadow Types</h2>
 		<code>
-		THREE.BasicShadowMap 
-		THREE.PCFShadowMap 
+		THREE.BasicShadowMap
+		THREE.PCFShadowMap
 		THREE.PCFSoftShadowMap
 		THREE.VSMShadowMap
 		</code>
 		<p>
 			These define the WebGLRenderer's [page:WebGLRenderer.shadowMap.type shadowMap.type] property.<br /><br />
-			[page:constant BasicShadowMap] gives unfiltered shadow maps - fastest, but 
+			[page:constant BasicShadowMap] gives unfiltered shadow maps - fastest, but
 			lowest quality.<br />
 			[page:constant PCFShadowMap] filters shadow maps using the
 			Percentage-Closer Filtering (PCF) algorithm (default).<br />
@@ -44,13 +44,13 @@
 			also cast shadows.
 		</p>
 
-		
+
 		<h2>Tone Mapping</h2>
 		<code>
-		THREE.NoToneMapping 
-		THREE.LinearToneMapping 
+		THREE.NoToneMapping
+		THREE.LinearToneMapping
 		THREE.ReinhardToneMapping
-		THREE.CineonToneMapping 
+		THREE.CineonToneMapping
 		THREE.ACESFilmicToneMapping
 		THREE.AgXToneMapping
 		THREE.NeutralToneMapping
@@ -62,9 +62,9 @@
 			monitor or mobile device's screen.
 		</p>
 		<p>
-			THREE.LinearToneMapping, THREE.ReinhardToneMapping, THREE.CineonToneMapping, THREE.ACESFilmicToneMapping, 
-			THREE.AgXToneMapping and THREE.NeutralToneMapping are built-inimplementations of tone mapping. 
-			THREE.CustomToneMapping expects a custom implementation by modyfing GLSL code of the material's fragment shader.
+			THREE.LinearToneMapping, THREE.ReinhardToneMapping, THREE.CineonToneMapping, THREE.ACESFilmicToneMapping,
+			THREE.AgXToneMapping and THREE.NeutralToneMapping are built-in implementations of tone mapping.
+			THREE.CustomToneMapping expects a custom implementation by modifying GLSL code of the material's fragment shader.
 			See the [example:webgl_tonemapping WebGL / tonemapping] example.
 		</p>
 		<p>

+ 1 - 3
docs/api/en/core/Clock.html

@@ -11,9 +11,7 @@
 
 		<p class="desc">
 			Object for keeping track of time. This uses
-			[link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now] if it is available, otherwise it reverts to the less
-			accurate
-			[link:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/now Date.now].
+			[link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now].
 		</p>
 
 		<h2>Constructor</h2>

+ 5 - 5
docs/api/en/objects/BatchedMesh.html

@@ -14,8 +14,8 @@
 		<p class="desc">
 			A special version of [page:Mesh] with multi draw batch rendering support. Use
 			[name] if you have to render a large number of objects with the same
-			material but with different world transformations. The usage of [name] will
-			help you to reduce the number of draw calls and thus improve the overall
+			material but with different geometries or world transformations. The usage of
+			[name] will help you to reduce the number of draw calls and thus improve the overall
 			rendering performance in your application.
 
 			<br/>
@@ -167,7 +167,7 @@
 		<p>
 			[page:Integer instanceId]: The id of an instance to get the visibility state of.
 		</p>
-		<p>Get whether the given instance is marked as "visible" or not.</p>		
+		<p>Get whether the given instance is marked as "visible" or not.</p>
 
 		<h3>
 			[method:Object getGeometryRangeAt]( [param:Integer geometryId], [param:Object target] )
@@ -181,7 +181,7 @@
 		<p>Get the range representing the subset of triangles related to the attached geometry, indicating the starting offset and count, or `null` if invalid.</p>
 		<p>Return an object of the form:</p>
 		<code>{ start: Integer, count: Integer }</code>
-	
+
 		<h3>
 			[method:Integer getGeometryIdAt]( [param:Integer instanceId] )
 		</h3>
@@ -313,7 +313,7 @@
 		</h3>
 		<p>
 			Resizes the available space in [name]'s vertex and index buffer attributes to the provided sizes. If the provided arguments shrink the geometry buffers
-			but there is not enough unused space at the end of the geometry attributes then an error is thrown. 
+			but there is not enough unused space at the end of the geometry attributes then an error is thrown.
 		</p>
 		<p>
 			[page:Integer maxVertexCount] - the max number of vertices to be used by all unique geometries to resize to.<br />

+ 62 - 0
docs/api/en/objects/ClippingGroup.html

@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:Group] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			A special version of the Group object that defines clipping planes for decendant objects.
+			ClippingGroups can be nested, with clipping planes accumulating by type: intersection or union.
+		</p>
+
+		<p>Note: ClippingGroup is only supported with WebGPURenderer.</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( )</h3>
+
+		<h2>Properties</h2>
+		<p>See the base [page:Group] class for common properties.</p>
+
+		<h3>[property:Boolean isClippingGroup]</h3>
+		<p>Read-only flag to check if a given object is of type [name].</p>
+
+		<h3>[property:Array clippingPlanes]</h3>
+		<p>
+			User-defined clipping planes specified as THREE.Plane objects in world
+			space. These planes apply to the objects that are children of this ClippingGroup.
+			Points in space whose signed distance to the plane is negative are clipped
+			(not rendered). See the [example:webgpu_clipping webgpu / clipping] example. Default is `[]`.
+		</p>
+
+		<h3>[property:Boolean enabled]</h3>
+		<p>Determines if the clipping planes defined by this object are applied. Default is `true`.</p>
+
+		<h3>[property:Boolean clipIntersection]</h3>
+		<p>
+			Changes the behavior of clipping planes so that only their intersection is
+			clipped, rather than their union. Default is `false`.
+		</p>
+
+		<h3>[property:Boolean clipShadows]</h3>
+		<p>
+			Defines whether to clip shadows according to the clipping planes specified
+			by this ClippingGroup. Default is `false`.
+		</p>
+
+		<h2>Methods</h2>
+		<p>See the base [page:Object3D] class for common methods.</p>
+
+		<h2>Source</h2>
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+		</p>
+	</body>
+</html>

+ 6 - 1
docs/api/en/renderers/WebGLRenderer.html

@@ -201,8 +201,13 @@ document.body.appendChild( renderer.domElement );
 			<li>`WEBGL_compressed_texture_s3tc`</li>
 			<li>`WEBGL_compressed_texture_pvrtc`</li>
 			<li>`WEBGL_compressed_texture_etc1`</li>
+			<li>See more: <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Using_Extensions#extension_list" target="_blank">Extension list</a></li>
 		</ul>
 
+		<p>
+			- [page:Boolean has]( [param:String extensionName] ): `true` if the extension is supported.
+		</p>
+
 		<h3>[property:string outputColorSpace]</h3>
 		<p>
 			Defines the output color space of the renderer. Default is [page:Textures THREE.SRGBColorSpace].
@@ -380,7 +385,7 @@ document.body.appendChild( renderer.domElement );
 		</p>
 
 		<h3>
-			[method:undefined copyTextureToTexture]( [param:Texture srcTexture], [param:Texture dstTexture], [param:Box2 srcRegion] | [param:Box3 srcRegion], [param:Vector2 dstPosition] | [param:Vector3 dstPosition], [param:Number dstLevel] )
+			[method:undefined copyTextureToTexture]( [param:Texture srcTexture], [param:Texture dstTexture], [param:Box2 srcRegion] | [param:Box3 srcRegion], [param:Vector2 dstPosition] | [param:Vector3 dstPosition], [param:Number srcLevel], [param:Number dstLevel] )
 		</h3>
 		<p>
 			Copies the pixels of a texture in the bounds '[page:Box3 srcRegion]' in the destination texture starting from the given position.

+ 1 - 2
docs/api/it/core/Clock.html

@@ -10,8 +10,7 @@
 		<h1>[name]</h1>
 
 		<p class="desc">
-      Oggetto per tenere traccia del tempo. Questa classe utilizza [link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now]
-      se disponibile, altrimenti utilizza il meno accurato [link:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/now Date.now].
+    	  Oggetto per tenere traccia del tempo. Questa classe utilizza [link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now].
 		</p>
 
 		<h2>Costruttore</h2>

+ 1 - 1
docs/api/ko/core/Clock.html

@@ -10,7 +10,7 @@
 		<h1>[name]</h1>
 
 		<p class="desc">
-		시간을 파악하는 객체입니다. [link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now]를 우선적으로 사용하며, 사용이 불가능할 때는 덜 정확한 [link:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/now Date.now]를 사용합니다.
+		시간을 파악하는 객체입니다. [link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now]
 		</p>
 
 

+ 1 - 2
docs/api/zh/core/Clock.html

@@ -9,8 +9,7 @@
 	<body>
 		<h1>[name]</h1>
 		<p class="desc">
-			该对象用于跟踪时间。如果[link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now]可用,则
-			Clock 对象通过该方法实现,否则回落到使用略欠精准的[link:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/now Date.now]来实现。
+			该对象用于跟踪时间。如果[link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now]。
 		</p>
 
 

+ 5 - 0
docs/api/zh/renderers/WebGLRenderer.html

@@ -141,6 +141,7 @@
 		- [page:Object get]( [param:String extensionName] ):
 			用于检查是否支持各种扩展,并返回一个对象,其中包含扩展的详细信息。
 			该方法检查以下扩展:<br />
+		</p>
 
 		<ul>
 			<li>*WEBGL_depth_texture*</li>
@@ -148,7 +149,11 @@
 			<li>*WEBGL_compressed_texture_s3tc*</li>
 			<li>*WEBGL_compressed_texture_pvrtc*</li>
 			<li>*WEBGL_compressed_texture_etc1*</li>
+			<li>查看更多:<a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Using_Extensions#extension_list" target="_blank">Extension list</a></li>
 		</ul>
+
+		<p>
+			- [page:Boolean has]( [param:String extensionName] ): 如果支持该扩展则返回 `true`。
 		</p>
 
 		<h3>[property:string outputColorSpace]</h3>

+ 5 - 0
docs/examples/en/controls/ArcballControls.html

@@ -132,6 +132,11 @@
 			Set to true to enable animations for rotation (damping) and focus operation. Default is true.
 		</p>
 
+		<h3>[property:Boolean enableFocus]</h3>
+		<p>
+			Enable or disable camera focusing on double-tap (or click) operations. Default is true.
+		</p>
+
 		<h3>[property:Boolean enableGrid]</h3>
 		<p>
 			When set to true, a grid will appear when panning operation is being performed (desktop interaction only). Default is false.

+ 2 - 0
docs/examples/en/exporters/GLTFExporter.html

@@ -52,6 +52,8 @@
 			<li>KHR_materials_volume</li>
 			<li>KHR_mesh_quantization</li>
 			<li>KHR_texture_transform</li>
+			<li>EXT_materials_bump</li>
+			<li>EXT_mesh_gpu_instancing</li>
 		</ul>
 
 		<p>

+ 6 - 0
docs/examples/en/lines/LineGeometry.html

@@ -75,6 +75,12 @@
 			The length must be a multiple of three.
 		</p>
 
+		<h3>[method:this setFromPoints]( [param:Array points] )</h3>
+		<p>
+			Replace the vertex positions with an array of points.
+			Can be either a `Vector3` or `Vector2` array.
+		</p>
+
 		<h2>Source</h2>
 
 		<p>

+ 1 - 1
docs/examples/en/loaders/MMDLoader.html

@@ -44,7 +44,7 @@
 				scene.add( mesh );
 
 			},
-			// called when loading is in progresses
+			// called when loading is in progress
 			function ( xhr ) {
 
 				console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

+ 1 - 1
docs/examples/en/loaders/OBJLoader.html

@@ -45,7 +45,7 @@
 				scene.add( object );
 
 			},
-			// called when loading is in progresses
+			// called when loading is in progress
 			function ( xhr ) {
 
 				console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

+ 1 - 1
docs/examples/en/loaders/PCDLoader.html

@@ -50,7 +50,7 @@
 				scene.add( points );
 
 			},
-			// called when loading is in progresses
+			// called when loading is in progress
 			function ( xhr ) {
 
 				console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

+ 1 - 1
docs/examples/en/loaders/PDBLoader.html

@@ -46,7 +46,7 @@
 				console.log( 'This molecule has ' + json.atoms.length + ' atoms' );
 
 			},
-			// called when loading is in progresses
+			// called when loading is in progress
 			function ( xhr ) {
 
 				console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

+ 1 - 1
docs/examples/en/loaders/SVGLoader.html

@@ -68,7 +68,7 @@
 				scene.add( group );
 
 			},
-			// called when loading is in progresses
+			// called when loading is in progress
 			function ( xhr ) {
 
 				console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

+ 1 - 1
docs/examples/en/loaders/TGALoader.html

@@ -42,7 +42,7 @@
 				console.log( 'Texture is loaded' );
 
 			},
-			// called when the loading is in progresses
+			// called when the loading is in progress
 			function ( xhr ) {
 
 				console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

+ 5 - 0
docs/examples/ko/controls/ArcballControls.html

@@ -132,6 +132,11 @@
 		true로 설정하여 회전 (감쇠)과 초점 맞추기 동작을 위한 애니메이션을 활성화합니다.기본값은 true입니다.
 	</p>
 
+	<h3>[property:Boolean enableFocus]</h3>
+	<p>
+		더블 탭(또는 클릭) 시 카메라 초점을 맞추는 기능을 활성화하려면 true로 설정합니다. 기본값은 true입니다.
+	</p>
+
 	<h3>[property:Boolean enableGrid]</h3>
 	<p>
 		true로 설정하면 패닝 동작을 할 때 모드가 나타날 것입니다 (데스크톱 상호 작용할 때만).기본값은 false입니다.

+ 5 - 0
docs/examples/zh/controls/ArcballControls.html

@@ -123,6 +123,11 @@
 		设置为 true 以启用旋转(阻尼)和聚焦操作的动画。默认为 true。
 	</p>
 
+	<h3>[property:Boolean enableFocus]</h3>
+	<p>
+		设置为 true 以在双击(或点击)时启用相机聚焦功能。默认值为 true。
+	</p>
+
 	<h3>[property:Boolean enableGrid]</h3>
 	<p>
 		设置为 true 时,执行平移操作时将出现网格(仅限桌面交互)。默认为 false。

+ 2 - 0
docs/examples/zh/exporters/GLTFExporter.html

@@ -50,6 +50,8 @@
 		<li>KHR_materials_volume</li>
 		<li>KHR_mesh_quantization</li>
 		<li>KHR_texture_transform</li>
+		<li>EXT_materials_bump</li>
+		<li>EXT_mesh_gpu_instancing</li>
 	</ul>
 
 	<p>

+ 1 - 1
docs/examples/zh/loaders/MMDLoader.html

@@ -44,7 +44,7 @@
 				scene.add( mesh );
 
 			},
-			// called when loading is in progresses
+			// called when loading is in progress
 			function ( xhr ) {
 
 				console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

+ 1 - 1
docs/examples/zh/loaders/OBJLoader.html

@@ -44,7 +44,7 @@
 				scene.add( object );
 
 			},
-			// called when loading is in progresses
+			// called when loading is in progress
 			function ( xhr ) {
 
 				console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

+ 1 - 1
docs/examples/zh/loaders/PCDLoader.html

@@ -50,7 +50,7 @@
 				scene.add( points );
 
 			},
-			// called when loading is in progresses
+			// called when loading is in progress
 			function ( xhr ) {
 
 				console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

+ 1 - 1
docs/examples/zh/loaders/PDBLoader.html

@@ -47,7 +47,7 @@
 				console.log( 'This molecule has ' + json.atoms.length + ' atoms' );
 
 			},
-			// called when loading is in progresses
+			// called when loading is in progress
 			function ( xhr ) {
 
 				console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

+ 1 - 1
docs/examples/zh/loaders/SVGLoader.html

@@ -68,7 +68,7 @@
 				scene.add( group );
 
 			},
-			// called when loading is in progresses
+			// called when loading is in progress
 			function ( xhr ) {
 
 				console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

+ 1 - 1
docs/examples/zh/loaders/TGALoader.html

@@ -41,7 +41,7 @@
 				console.log( 'Texture is loaded' );
 
 			},
-			// called when the loading is in progresses
+			// called when the loading is in progress
 			function ( xhr ) {
 
 				console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

+ 4 - 1
docs/list.json

@@ -267,6 +267,7 @@
 			"Objects": {
 				"BatchedMesh": "api/en/objects/BatchedMesh",
 				"Bone": "api/en/objects/Bone",
+				"ClippingGroup": "api/en/objects/ClippingGroup",
 				"Group": "api/en/objects/Group",
 				"InstancedMesh": "api/en/objects/InstancedMesh",
 				"Line": "api/en/objects/Line",
@@ -1221,6 +1222,7 @@
 				"선 그리기": "manual/ko/introduction/Drawing-lines",
 				"텍스트 만들기": "manual/ko/introduction/Creating-text",
 				"3D 모델 불러오기": "manual/ko/introduction/Loading-3D-models",
+				"라이브러리 및 플러그인": "manual/en/introduction/Libraries-and-Plugins",
 				"FAQ": "manual/ko/introduction/FAQ",
 				"참고 링크": "manual/ko/introduction/Useful-links"
 			},
@@ -1231,7 +1233,8 @@
 				"VR 컨텐츠를 만드는 방법": "manual/ko/introduction/How-to-create-VR-content",
 				"후처리 사용 방법": "manual/ko/introduction/How-to-use-post-processing",
 				"행렬 변환": "manual/ko/introduction/Matrix-transformations",
-				"애니메이션 시스템": "manual/ko/introduction/Animation-system"
+				"애니메이션 시스템": "manual/ko/introduction/Animation-system",
+				"색상 관리": "manual/ko/introduction/Color-management"
 			}
 
 		},

+ 2 - 3
docs/manual/fr/introduction/How-to-use-post-processing.html

@@ -59,8 +59,7 @@
 
 		<p>
 			Notre composer est maintenant prêt, il est donc possible de configurer la chaîne d'effets de post-processing. Ces effets (passes) sont chargés de la création
-			de l'apparence visuelle finale de l'application. Ils sont traités dans l'ordre de leur ajout/insertion. In our example, the instance of `RenderPass`
-			is executed first, then the instance of `GlitchPass` and finally `OutputPass`. Le dernier effet activé de la chaîne est automatiquement rendu dans la scène. Le setup
+			de l'apparence visuelle finale de l'application. Ils sont traités dans l'ordre de leur ajout/insertion. Dans notre exemple, l'instance de `RenderPass` est exécutée en premier, puis l'instance de `GlitchPass` et enfin `OutputPass`. Le dernier effet activé de la chaîne est automatiquement rendu dans la scène. Le setup
 			des effets ressemble à ça:
 		</p>
 
@@ -77,7 +76,7 @@
 
 		<p>
 			`RenderPass` est normalement placé au début de la chaîne pour fournir la scène rendue en tant qu'entrée pour les prochaines étapes de post-processing. Dans notre cas,
-			`GlitchPass` va utiliser les données de l'image pour appliquer un effet de glitch.  `OutputPass` is usually the last pass in the chain which performs sRGB color space conversion and optional tone mapping.
+			`GlitchPass` va utiliser les données de l'image pour appliquer un effet de glitch.  `OutputPass` est généralement le dernier passage de la chaîne qui effectue la conversion de l'espace colorimétrique sRGB et le mappage tonal optionnel.
 			Regardez cet [link:https://threejs.org/examples/webgl_postprocessing_glitch exemple live] pour voir cela en action.
 		</p>
 

+ 265 - 0
docs/manual/ko/introduction/Color-management.html

@@ -0,0 +1,265 @@
+<!DOCTYPE html>
+<html lang="ko">
+
+<head>
+	<meta charset="utf-8">
+	<base href="../../../" />
+	<script src="page.js"></script>
+	<link type="text/css" rel="stylesheet" href="page.css" />
+	<style>
+		blockquote {
+			font-size: 0.8em;
+			line-height: 1.5em;
+			margin-left: 0;
+			border-left: 4px solid #cccccc;
+			padding: 1em 2em 1em 2em;
+		}
+
+		blockquote p:first-child {
+			margin-top: 0;
+		}
+
+		blockquote p:last-child {
+			margin-bottom: 0;
+		}
+
+		figure {
+			width: 100%;
+			margin: 1em 0;
+			font-style: italic;
+		}
+
+		figure img {
+			width: 100%;
+		}
+
+		figure.float {
+			float: right;
+			max-width: 30%;
+			margin: 1em;
+		}
+
+		@media all and ( max-width: 640px ) {
+
+			figure.float {
+				float: none;
+				max-width: 100%;
+			}
+
+		}
+	</style>
+</head>
+
+<body>
+	<h1>색상 관리[name]</h1>
+
+	<h2>색상 공간이란 무엇입니까?</h2>
+
+	<p>
+		각 색상 공간은 정밀도 및 디스플레이 기술과 관련된 기술적 제한을 충족하는 동시에 다양한 색상을 지원하기 위해 선택된 여러 설계 결정의 집합입니다.3D 에셋을 만들거나 장면에 3D 에셋을 어셈블할 때 이러한 속성이 무엇인지, 한 색상 공간의 속성과 장면의 다른 색상 공간의 관계를 이해하는 것이 중요합니다.
+	</p>
+
+	<figure class="float">
+		<img src="resources/srgb_gamut.png" alt="">
+		<figcaption>
+			CIE 1931 색상 차트에 표시된 sRGB 색상 및 흰색 점(D65)을 참조하십시오.색상 영역은 3D 볼륨인 sRGB 색재현율의 2D 투영을 나타냅니다.출처: <a href="https://en.wikipedia.org/wiki/SRGB" target="_blank" rel="noopener">Wikipedia</a>
+		</figcaption>
+	</figure>
+
+	<ul>
+		<li>
+			<b>원색:</b>원색(예를 들어 빨간색, 녹색, 파란색)은 절대적인 것이 아니다.그들은
+			제한된 정밀도 제약조건을 기반으로 가시 스펙트럼에서 선택
+			사용 가능한 디스플레이 장치의 성능색상은 원색의 비율을 나타냅니다.
+		</li>
+		<li>
+			<b> 흰색: </b> 대부분의 색상 공간은 다음과 같이 설계되었습니다.
+			원색 <i>R=G=B</i>는 색상이 없거나 "무채색" 으로 표시됩니다.모양
+			흰색이나 회색과 같은 소색 차이의 변화는 인간의 지각에 달려 있고 인간의 지각은
+			어느 정도 관찰자의 배경에 달려 있다.색상 공간의 균형을 맞추려면 흰색 점을 지정합니다.
+			이러한 요구 사항.sRGB 색상 공간에 정의된 흰색 점은
+			[link:https://en.wikipedia.org/wiki/Illuminant_D65D65]。
+		</li>
+		<li>
+			<b> 전송 함수: </b> 색재현율과 색상 모델을 선택한 후에도
+			숫자와 색상 공간 사이의 매핑을 정의합니다 (전달 함수).<i>r=0.5</i> 여부
+			물리적 조도가 <i>r=1.0</i>보다 50% 낮음을 나타냅니까?또는 인식에 따라 밝기 50% 감소
+			보통 사람의 눈?이것들은 서로 다른 것이다. 이런 차이는
+			수학 함수전송 함수는 <i> 선형 </i> 또는 <i> 비선형 </i> 일 수 있습니다.
+			색상 공간에 대한 대상입니다.sRGB는 비선형 전송 함수를 정의합니다.그것들
+			함수는 가끔 <i>gamma 함수 </i>와 비슷하지만 "gamma"는
+			애매모호하니 이런 상황에서는 피해야 한다.
+		</li>
+	</ul>
+
+		원색, 흰색 점 및 전송 함수라는 세 개의 매개변수는 각 매개변수가 특정 대상에 대해 선택된 색상 공간을 정의합니다.매개변수를 정의한 후에는 다음과 같은 추가 용어가 도움이 됩니다.
+
+		<ul>
+			<li>
+			<b> 색상 모델: </b> 선택한 색재현율에서 숫자로 색상을 식별하는 구문 - 색상의 좌표계입니다.three.js에서는 주로 RGB 색상에 초점을 맞춥니다.세 개의 좌표 <i>r, g, b∈[0,1]</i>("닫힌 도메인") 또는<i> r, g, b∈[0, ></i>("개역"), 각 마스터 도메인의 일부를 나타냅니다.색상.기타 색상 모델(HSL, Lab, LCH)은 일반적으로 예술 제어에 사용됩니다.
+			</li>
+			<li>
+			<b> 색재현율: </b> 원색과 흰색 점을 선택한 경우 가시 스펙트럼 내의 볼륨 (색재현율)이 볼륨에 포함되지 않는 색상 (색상 외부) 닫힌 도메인 [0,1] RGB 값으로는 표시할 수 없습니다.열린 도메인 [0, 에서 색재현율은 다음과 같습니다.기술적으로 무한하다.
+			</li>
+			</ul>
+
+	<p>
+		[page: SRGBColorSpace]("sRGB") 및 [page: LinearSRGBColorSpace]("Linear-sRGB") 두 가지 일반적인 색상 공간을 고려합니다.둘 다 같은 원색과 흰색 점을 사용하기 때문에 같은 색재현율을 가집니다.둘 다 RGB 색상 모델을 사용합니다.이들은 전송 함수에서만 다릅니다. 선형 sRGB는 물리적 빛 강도와 선형 관계입니다.sRGB는 비선형 sRGB 전달 함수를 사용하여 사람의 눈이 빛을 감지하는 방식과 일반적인 디스플레이 장치의 응답성에 더 가깝습니다.
+	</p>
+
+	<p>
+		이런 차이는 매우 중요하다.조명 계산 및 기타 렌더링 작업은 일반적으로 선형 색상 공간에서 수행되어야 합니다.그러나 선형 색상은 이미지나 프레임 버퍼에서 저장 효율이 낮고 인간 관찰자가 볼 때 올바르게 보이지 않습니다.따라서 텍스쳐 입력 및 최종 렌더링 이미지에는 일반적으로 비선형 sRGB 색상 공간이 사용됩니다.
+	</p>
+
+	<blockquote>
+		<p>
+			ℹ️ <i><b>NOTICE:</b> 일부 현대 모니터는 Display-P3와 같은 더 넓은 색재현율을 지원하지만 네트워크 플랫폼의 그래픽 API는 sRGB에 크게 의존합니다.현재 three.js를 사용하는 응용 프로그램은 일반적으로 sRGB 및 Linear sRGB 색상 공간만 사용합니다.</i>
+		</p>
+	</blockquote>
+
+	<h2>색채공간의 역할</h2>
+
+	<p>
+		현대 렌더링 방법에 필요한 선형 워크플로우는 일반적으로 여러 색상 공간과 관련되며 각 색상 공간은 특정 역할에 할당됩니다.선형 및 비선형 색상 공간은 다음과 같이 서로 다른 역할에 적용됩니다.
+	</p>
+
+	<h3>색상 공간 가져오기</h3>
+
+	<p>
+    three.js에 제공되는 색상 -- 색상 선택기, 텍스쳐, 3D 모델 및 다른 소스에서 가져온 각 색상 공간은 연관되어 있습니다.Linear sRGB 작업 색상 공간에 아직 없는 색상을 변환하고 텍스쳐에 올바른 <i>texture.colorSpace</i> 할당을 할당해야 합니다.세 가지 조건이 충족되면 특정 변환을 자동으로 수행할 수 있습니다 (sRGB의 16진수 및 CSS 색상).색상을 초기화하기 전에 ColorManagement API를 활성화합니다.
+	</p>
+
+	<code>
+    THREE.ColorManagement.enabled = true;
+	</code>
+
+	<p>
+		THREE.ColorManagement 기본적으로 활성화됩니다.
+	</p>
+
+	<ul>
+		<li>
+			<b>Materials, lights, and shaders:</b> 재료, 조명 및 셰이더의 색상은 RGB 컴포넌트를 Linear sRGB 작업 색상 공간에 저장합니다.
+		</li>
+		<li>
+			<b>Vertex colors:</b> [page:BufferAttribute BufferAttributes] RGB 컴포넌트 저장 선형 sRGB 작업 색상 공간.
+		</li>
+		<li>
+			<b> 색상 텍스처: </b>.map 또는.emissiveMap과 같은 색상 정보가 포함된 PNG 또는 JPEG[페이지: 텍스처 텍스처]는 닫힌 도메인 sRGB 색상 공간을 사용하며 <i>Texture.colorSpace=SRGBColorSpace</i>를 사용해야 합니다.OpenEXR(.envMap 또는.lightMap의 경우) 같은 형식은 <i>texture.colorSpace LinearSRGBColorSpace</i>로 표시된 선형 sRGB 색상 공간을 사용합니다.
+			또한 개역 [0,]의 값을 포함할 수 있습니다.
+			</li>
+			<li>
+			<b> 비컬러 텍스쳐: </b> 색상 정보를 저장하지 않는 텍스쳐(예:.normalMap 또는.rawnessMap)에는 연관된 색상 공간이 없으며, 일반적으로 (기본값) 텍스쳐 메모 <i> texture.colorSpace = NoColorSpace</i> 를 사용합니다.기술적인 이유로 비색상 데이터가 다른 비선형 인코딩으로 표시될 수 있는 경우는 극히 일부입니다.
+		</li>
+	</ul>
+
+	<blockquote>
+		<p>
+			⚠️ <i><b> 경고: </b> 많은 3D 모델의 형식이 색상 공간 정보를 올바르거나 일관되게 정의하지 않습니다.three.js가 대부분의 상황을 처리하려고 시도하지만 이전 파일 형식의 문제는 흔합니다.최상의 결과를 얻으려면 glTF 2.0([page:GLTFLoader])을 사용하고 가능한 한 빨리 온라인 뷰어에서 3D 모델을 테스트하여 자산 자체가 정확한지 확인하십시오</i>
+		</p>
+	</blockquote>
+
+	<h3>작업 색상 공간</h3>
+
+	<p>
+		렌더링, 보간 및 기타 많은 작업은 RGB 컴포넌트가 실제 조명에 비례하는 열린 도메인 선형 작업 색상 공간에서 수행되어야 합니다.three.js에서 작업 색상 공간은 Linear-sRGB입니다.
+	</p>
+
+	<h3>출력 색상 공간</h3>
+
+	<p>
+		디스플레이 장치, 이미지 또는 비디오로 출력하는 것은 열린 도메인의 Linear-sRGB 작업 색상 공간에서 다른 색상 공간으로 변환하는 것과 관련될 수 있습니다.이 변환은 기본 렌더링 프로세스([page:WebGLRender.outputColorSpace]) 또는 사후 처리 프로세스에서 수행할 수 있습니다.
+	</p>
+
+	<code>
+    renderer.outputColorSpace = THREE.SRGBColorSpace; // optional with post-processing
+	</code>
+
+	<ul>
+		<li>
+			<b> 표시: </b> WebGL 캔버스에 기록된 색상은 sRGB 색상 공간에 있어야 합니다.
+		</li>
+		<li>
+			<b>Image:</b>이미지를 쓰는 색상은 형식과 용도에 맞는 색상 공간을 사용해야 합니다.PNG 또는 JPEG 텍스쳐를 쓴 전체 렌더링 이미지는 일반적으로 sRGB 색상 공간을 사용합니다.송신, 조명 맵 또는 [0,1] 범위에 국한되지 않는 다른 데이터를 포함하는 이미지는 일반적으로 OpenEXR과 같은 Open 도메인 선형 sRGB 색상 공간과 호환되는 이미지 형식을 사용합니다.
+		</li>
+	</ul>
+
+	<blockquote>
+		<p>
+			⚠️ <i><b> 경고: </b> 렌더링 대상은 sRGB 또는 선형 sRGB를 사용할 수 있습니다.sRGB는 제한된 정밀도를 더 잘 활용합니다.닫힌 도메인에서 8 비트는 일반적으로 sRGB에 충분하지만 선형 sRGB는 ≥ 12 비트 (반 부동 소수점) 가 필요할 수 있습니다.후속 라인 단계에서 선형 sRGB 입력이 필요한 경우 추가 변환으로 인해 적은 성능 비용이 발생할 수 있습니다</i>
+		</p>
+	</blockquote>
+
+	<p>
+    [page:ShaderMaterial] 및 [page:RawShaderMaterial] 기반 사용자 지정 재료는 자체 출력 색상 공간 변환을 수행해야 합니다."ShaderMaterial" 인스턴스의 경우 "colorspace_fragment" 셰이더 블록을 세그먼트 셰이더의 "main()" 함수에 추가하면 충분합니다.
+	</p>
+
+	<h2>과 협력 THREE.Color 인스턴스</h2>
+
+	<p>
+		[page:Color] 인스턴스를 읽거나 수정하는 방법은 데이터가 three.js 작업 색상 공간인 Linear sRGB에 이미 있다고 가정합니다.RGB 및 HSL 구성 요소는 Color 인스턴스에 저장된 데이터의 직접 표현으로 암시적으로 변환되지 않습니다.색상 데이터는 <i>를 사용하여 명시적으로 변환할 수 있습니다 <i>.convertLinearToSRGB()</i>
+		or <i>.convertSRGBToLinear()</i>.
+	</p>
+
+	<code>
+		// RGB components (no change).
+		color.r = color.g = color.b = 0.5;
+		console.log( color.r ); // → 0.5
+
+		// Manual conversion.
+		color.r = 0.5;
+		color.convertSRGBToLinear();
+		console.log( color.r ); // → 0.214041140
+	</code>
+
+	<p>
+		<i>ColorManagement.enabled=true</i>(권장)를 설정하면 일부 변환이 자동으로 수행됩니다.16진수와 CSS 색상은 일반적으로 sRGB이기 때문에 [page:Color] 메서드는 setter에서 이러한 입력을 sRGB에서 Linear sRGB로 자동 변환하거나 getter에서 16진수 또는 CSS 출력을 반환할 때 Linear sRG에서 sRGB로 변환합니다.
+	</p>
+
+	<code>
+		// Hexadecimal conversion.
+		color.setHex( 0x808080 );
+		console.log( color.r ); // → 0.214041140
+		console.log( color.getHex() ); // → 0x808080
+
+		// CSS conversion.
+		color.setStyle( 'rgb( 0.5, 0.5, 0.5 )' );
+		console.log( color.r ); // → 0.214041140
+
+		// Override conversion with 'colorSpace' argument.
+		color.setHex( 0x808080, LinearSRGBColorSpace );
+		console.log( color.r ); // → 0.5
+		console.log( color.getHex( LinearSRGBColorSpace ) ); // → 0x808080
+		console.log( color.getHex( SRGBColorSpace ) ); // → 0xBCBCBC
+	</code>
+
+	<h2>일반적인 오류</h2>
+
+	<p>
+		단일 색상이나 텍스쳐 구성이 잘못되면 예상보다 더 어둡거나 밝게 표시됩니다.렌더기의 출력 색상 공간 구성이 잘못되면 전체 장면이 더 어둡게 보일 수 있습니다 (예: sRGB로 변환할 수 없음). 또는 더 밝게 보일 수 있습니다 (예: 사후 처리된 sRGB 이중 변환).각 상황에서 문제가 고르지 않을 수 있으며 조명을 단순히 증가 / 감소한다고 해서 문제가 해결되지는 않습니다.
+	</p>
+
+	<p>
+		다음과 같은 상황이 발생하면 더욱 미묘한 문제가 나타난다<i> 둘 다 </i>색상 공간 입력과 출력 색상 공간이 올바르지 않습니다. 전체적인 밝기 수준은 좋을 수 있지만 다른 조명에서 색상이 예기치 않게 변경되거나 그림자가 예상보다 과장되고 부드러워 보일 수 있습니다.이 두 가지 잘못은 결코 하나의 정확성과 같지 않다. 중요한 것은 일이다 색상 공간은 선형 (장면 참조) 이고 출력 색상 공간은 비선형 (디스플레이 참조) 입니다.
+	</p>
+
+	<h2>추가 읽기</h2>
+
+	<ul>
+		<li>
+			<a href="https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-24-importance-being-linear" target="_blank" rel="noopener">GPU Gems 3: 선형의 중요성</a>,저자: Larry Gritz and Eugene d'Eon
+		</li>
+		<li>
+			<a href="https://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/" target="_blank" rel="noopener">모든 프로그래머는 gamma에 대해 알아야 합니다</a>, 저자:John Novak
+		</li>
+		<li>
+			<a href="https://hg2dc.com/" target="_blank" rel="noopener">디지털 색상 보행시선 안내서</a>,저자: Troy Sobotka
+		</li>
+		<li>
+			<a href="https://docs.blender.org/manual/en/latest/render/color_management.html" target="_blank" rel="noopener">색상 관리</a>,저자: Blender
+		</li>
+	</ul>
+
+</body>
+
+</html>

+ 117 - 0
docs/manual/ko/introduction/Libraries-and-Plugins.html

@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<html lang="ko">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		<h1>라이브러리 및 플러그인[name]</h1>
+
+		<p class="desc">
+			three.js를 위해 외부에서 개발된 호환 라이브러리와 플러그인을 나열합니다.이것목록 및 관련 패키지는 커뮤니티에서 유지 관리되며 보장되지 않음최신 상태를 유지합니다.이 목록을 업데이트하려면 PR을 수행하십시오!
+		</p>
+
+		<h3>물리적</h3>
+
+		<ul>
+			<li>[link:https://github.com/lo-th/Oimo.js/ Oimo.js]</li>
+			<li>[link:https://enable3d.io/ enable3d]</li>
+			<li>[link:https://github.com/kripken/ammo.js/ ammo.js]</li>
+			<li>[link:https://github.com/pmndrs/cannon-es cannon-es]</li>
+			<li>[link:https://rapier.rs/ rapier]</li>
+			<li>[link:https://github.com/jrouwe/JoltPhysics.js Jolt]</li>
+			
+		</ul>
+
+		<h3>후처리</h3>
+
+		<p>
+			In addition to the [link:https://github.com/mrdoob/three.js/tree/dev/examples/jsm/postprocessing official three.js postprocessing effects],
+			support for some additional effects and frameworks are available through external libraries.
+		</p>
+
+		<ul>
+			<li>[link:https://github.com/vanruesc/postprocessing postprocessing]</li>
+		</ul>
+
+		<h3>교차점 및 광선 투사 성능</h3>
+
+		<ul>
+			<li>[link:https://github.com/gkjohnson/three-mesh-bvh three-mesh-bvh]</li>
+		</ul>
+
+		<h3>경로 추적</h3>
+		
+		<ul>
+			<li>[link:https://github.com/gkjohnson/three-gpu-pathtracer three-gpu-pathtracer]</li>
+		</ul>
+		
+		<h3>파일 형식</h3>
+
+		<p>
+			In addition to the [link:https://github.com/mrdoob/three.js/tree/dev/examples/jsm/loaders official three.js loaders],
+			support for some additional formats is available through external libraries.
+			[link:https://github.com/mrdoob/three.js/tree/dev/examples/jsm/loaders공식 three.js 로더]외에도,일부 추가 형식에 대한 지원은 외부 라이브러리를 통해 가능합니다
+		</p>
+
+		<ul>
+			<li>[link:https://github.com/gkjohnson/urdf-loaders/tree/master/javascript urdf-loader]</li>
+			<li>[link:https://github.com/NASA-AMMOS/3DTilesRendererJS 3d-tiles-renderer-js]</li>
+			<li>[link:https://github.com/kaisalmen/WWOBJLoader WebWorker OBJLoader]</li>
+			<li>[link:https://github.com/IFCjs/web-ifc-three IFC.js]</li>
+		</ul>
+
+		<h3>기하학</h3>
+
+		<ul>
+			<li>[link:https://github.com/spite/THREE.MeshLine THREE.MeshLine]</li>
+		</ul>
+
+		<h3>3D 텍스트 및 레이아웃</h3>
+
+		<ul>
+			<li>[link:https://github.com/protectwise/troika/tree/master/packages/troika-three-text troika-three-text]</li>
+			<li>[link:https://github.com/felixmariotto/three-mesh-ui three-mesh-ui]</li>
+		</ul>
+
+		<h3>입자계</h3>
+
+		<ul>
+			<li>[link:https://github.com/Alchemist0823/three.quarks three.quarks]</li>
+			<li>[link:https://github.com/creativelifeform/three-nebula three-nebula]</li>
+		</ul>
+
+		<h3>역기구학</h3>
+
+		<ul>
+			<li>[link:https://github.com/jsantell/THREE.IK THREE.IK]</li>
+			<li>[link:https://github.com/lo-th/fullik fullik]</li>
+			<li>[link:https://github.com/gkjohnson/closed-chain-ik-js closed-chain-ik]</li>
+		</ul>
+
+		<h3>게임 AI</h3>
+
+		<ul>
+			<li>[link:https://mugen87.github.io/yuka/ yuka]</li>
+			<li>[link:https://github.com/donmccurdy/three-pathfinding three-pathfinding]</li>
+			<li>[link:https://github.com/isaac-mason/recast-navigation-js recast-navigation-js]</li>
+		</ul>
+
+		<h3>포장 및 프레임</h3>
+
+		<ul>
+			<li>[link:https://aframe.io/ A-Frame]</li>
+			<li>[link:https://lume.io/ Lume] - Three 기반 3D 그래픽 HTML 요소.</li>
+			<li>[link:https://github.com/pmndrs/react-three-fiber react-three-fiber] - Three 기반 3D 그래픽 React 구성 요소.</li>
+			<li>[link:https://threepipe.org/ threepipe] - three.js를 사용하여 렌더링하는 다기능 3D 뷰어 프레임워크.</li>
+			<li>[link:https://github.com/ecsyjs/ecsy-three ECSY]</li>
+			<li>[link:https://threlte.xyz/ Threlte] - Three 기반 3D 그래픽 Svelte 구성 요소.</li>
+			<li>[link:https://needle.tools/ Needle Engine]</li>
+			<li>[link:https://tresjs.org/ tresjs] - Three 기반 3D 그래픽 Vue 어셈블리.</li>
+			<li>[link:https://giro3d.org Giro3D] - 지리 공간 2D, 2.5D 및 3D 데이터와의 시각화 및 상호 작용을 위한 Three 기반 다기능 프레임워크.</li>
+		</ul>
+
+	</body>
+</html>

+ 2 - 0
examples/files.json

@@ -335,8 +335,10 @@
 		"webgpu_lights_custom",
 		"webgpu_lights_ies_spotlight",
 		"webgpu_lights_phong",
+		"webgpu_lights_physical",
 		"webgpu_lights_rectarealight",
 		"webgpu_lights_selective",
+		"webgpu_lights_spotlight",
 		"webgpu_lights_tiled",
 		"webgpu_lines_fat_wireframe",
 		"webgpu_lines_fat",

+ 5 - 5
examples/index.html

@@ -68,7 +68,7 @@
 
 		const links = {};
 		const validRedirects = new Map();
-		const container = document.createElement( 'div' );
+		const fragment = document.createDocumentFragment();
 
 		let selected = null;
 
@@ -76,8 +76,6 @@
 
 		async function init() {
 
-			content.appendChild( container );
-
 			viewSrcButton.style.display = 'none';
 
 			const files = await ( await fetch( 'files.json' ) ).json();
@@ -90,14 +88,14 @@
 				const header = document.createElement( 'h2' );
 				header.textContent = key;
 				header.setAttribute( 'data-category', key );
-				container.appendChild( header );
+				fragment.appendChild( header );
 
 				for ( let i = 0; i < category.length; i ++ ) {
 
 					const file = category[ i ];
 
 					const link = createLink( file, tags[ file ] );
-					container.appendChild( link );
+					fragment.appendChild( link );
 
 					links[ file ] = link;
 					validRedirects.set( file, file + '.html' );
@@ -106,6 +104,8 @@
 
 			}
 
+			content.appendChild( fragment );
+
 			if ( window.location.hash !== '' ) {
 
 				const file = window.location.hash.substring( 1 );

+ 1 - 10
examples/jsm/capabilities/WebGPU.js

@@ -1,13 +1,4 @@
-if ( self.GPUShaderStage === undefined ) {
-
-	self.GPUShaderStage = { VERTEX: 1, FRAGMENT: 2, COMPUTE: 4 };
-
-}
-
-// statics
-
-let isAvailable = navigator.gpu !== undefined;
-
+let isAvailable = ( typeof navigator !== 'undefined'  && navigator.gpu !== undefined );
 
 if ( typeof window !== 'undefined' && isAvailable ) {
 

+ 25 - 21
examples/jsm/controls/ArcballControls.js

@@ -204,6 +204,7 @@ class ArcballControls extends Controls {
 		this.enableRotate = true;
 		this.enableZoom = true;
 		this.enableGizmos = true;
+		this.enableFocus = true;
 
 		this.minDistance = 0;
 		this.maxDistance = Infinity;
@@ -697,7 +698,7 @@ class ArcballControls extends Controls {
 
 	onDoubleTap( event ) {
 
-		if ( this.enabled && this.enablePan && this.scene != null ) {
+		if ( this.enabled && this.enablePan && this.enableFocus && this.scene != null ) {
 
 			this.dispatchEvent( _startEvent );
 
@@ -2036,29 +2037,32 @@ class ArcballControls extends Controls {
 		let state;
 		if ( this.object.isOrthographicCamera ) {
 
-			state = JSON.stringify( { arcballState: {
+			state = JSON.stringify( {
+				arcballState: {
+					cameraFar: this.object.far,
+					cameraMatrix: this.object.matrix,
+					cameraNear: this.object.near,
+					cameraUp: this.object.up,
+					cameraZoom: this.object.zoom,
+					gizmoMatrix: this._gizmos.matrix
 
-				cameraFar: this.object.far,
-				cameraMatrix: this.object.matrix,
-				cameraNear: this.object.near,
-				cameraUp: this.object.up,
-				cameraZoom: this.object.zoom,
-				gizmoMatrix: this._gizmos.matrix
-
-			} } );
+				}
+			} );
 
 		} else if ( this.object.isPerspectiveCamera ) {
 
-			state = JSON.stringify( { arcballState: {
-				cameraFar: this.object.far,
-				cameraFov: this.object.fov,
-				cameraMatrix: this.object.matrix,
-				cameraNear: this.object.near,
-				cameraUp: this.object.up,
-				cameraZoom: this.object.zoom,
-				gizmoMatrix: this._gizmos.matrix
+			state = JSON.stringify( {
+				arcballState: {
+					cameraFar: this.object.far,
+					cameraFov: this.object.fov,
+					cameraMatrix: this.object.matrix,
+					cameraNear: this.object.near,
+					cameraUp: this.object.up,
+					cameraZoom: this.object.zoom,
+					gizmoMatrix: this._gizmos.matrix
 
-			} } );
+				}
+			} );
 
 		}
 
@@ -2233,7 +2237,7 @@ class ArcballControls extends Controls {
 	 * @param {Matrix4} camera Transformation to be applied to the camera
 	 * @param {Matrix4} gizmos Transformation to be applied to gizmos
 	 */
-	 setTransformationMatrices( camera = null, gizmos = null ) {
+	setTransformationMatrices( camera = null, gizmos = null ) {
 
 		if ( camera != null ) {
 
@@ -2620,7 +2624,7 @@ class ArcballControls extends Controls {
 				this.applyTransformMatrix( this.scale( newDistance / distance, this._gizmos.position ) );
 				this.updateMatrixState();
 
-			 }
+			}
 
 			//check fov
 			if ( this.object.fov < this.minFov || this.object.fov > this.maxFov ) {

+ 41 - 9
examples/jsm/controls/OrbitControls.js

@@ -784,11 +784,19 @@ class OrbitControls extends Controls {
 
 				if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
 
-					this._rotateUp( _twoPI * this.rotateSpeed / this.domElement.clientHeight );
+					if ( this.enableRotate ) {
+
+						this._rotateUp( _twoPI * this.rotateSpeed / this.domElement.clientHeight );
+
+					}
 
 				} else {
 
-					this._pan( 0, this.keyPanSpeed );
+					if ( this.enablePan ) {
+
+						this._pan( 0, this.keyPanSpeed );
+
+					}
 
 				}
 
@@ -799,11 +807,19 @@ class OrbitControls extends Controls {
 
 				if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
 
-					this._rotateUp( - _twoPI * this.rotateSpeed / this.domElement.clientHeight );
+					if ( this.enableRotate ) {
+
+						this._rotateUp( - _twoPI * this.rotateSpeed / this.domElement.clientHeight );
+
+					}
 
 				} else {
 
-					this._pan( 0, - this.keyPanSpeed );
+					if ( this.enablePan ) {
+
+						this._pan( 0, - this.keyPanSpeed );
+
+					}
 
 				}
 
@@ -814,11 +830,19 @@ class OrbitControls extends Controls {
 
 				if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
 
-					this._rotateLeft( _twoPI * this.rotateSpeed / this.domElement.clientHeight );
+					if ( this.enableRotate ) {
+
+						this._rotateLeft( _twoPI * this.rotateSpeed / this.domElement.clientHeight );
+
+					}
 
 				} else {
 
-					this._pan( this.keyPanSpeed, 0 );
+					if ( this.enablePan ) {
+
+						this._pan( this.keyPanSpeed, 0 );
+
+					}
 
 				}
 
@@ -829,11 +853,19 @@ class OrbitControls extends Controls {
 
 				if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
 
-					this._rotateLeft( - _twoPI * this.rotateSpeed / this.domElement.clientHeight );
+					if ( this.enableRotate ) {
+
+						this._rotateLeft( - _twoPI * this.rotateSpeed / this.domElement.clientHeight );
+
+					}
 
 				} else {
 
-					this._pan( - this.keyPanSpeed, 0 );
+					if ( this.enablePan ) {
+
+						this._pan( - this.keyPanSpeed, 0 );
+
+					}
 
 				}
 
@@ -1340,7 +1372,7 @@ function onMouseWheel( event ) {
 
 function onKeyDown( event ) {
 
-	if ( this.enabled === false || this.enablePan === false ) return;
+	if ( this.enabled === false ) return;
 
 	this._handleKeyDown( event );
 

+ 2 - 5
examples/jsm/controls/PointerLockControls.js

@@ -127,14 +127,11 @@ function onMouseMove( event ) {
 
 	if ( this.enabled === false || this.isLocked === false ) return;
 
-	const movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
-	const movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
-
 	const camera = this.object;
 	_euler.setFromQuaternion( camera.quaternion );
 
-	_euler.y -= movementX * 0.002 * this.pointerSpeed;
-	_euler.x -= movementY * 0.002 * this.pointerSpeed;
+	_euler.y -= event.movementX * 0.002 * this.pointerSpeed;
+	_euler.x -= event.movementY * 0.002 * this.pointerSpeed;
 
 	_euler.x = Math.max( _PI_2 - this.maxPolarAngle, Math.min( _PI_2 - this.minPolarAngle, _euler.x ) );
 

+ 7 - 5
examples/jsm/csm/CSMShadowNode.js

@@ -5,11 +5,13 @@ import {
 	Matrix4,
 	Box3,
 	Object3D,
-	WebGLCoordinateSystem
-} from 'three';
+	WebGLCoordinateSystem,
+	NodeUpdateType,
+	Node
+} from 'three/webgpu';
 
 import { CSMFrustum } from './CSMFrustum.js';
-import { viewZToOrthographicDepth, reference, uniform, float, vec4, vec2, If, Fn, min, renderGroup, positionView, Node, NodeUpdateType, shadow } from 'three/tsl';
+import { viewZToOrthographicDepth, reference, uniform, float, vec4, vec2, If, Fn, min, renderGroup, positionView, shadow } from 'three/tsl';
 
 const _cameraToLightMatrix = new Matrix4();
 const _lightSpaceFrustum = new CSMFrustum();
@@ -253,7 +255,7 @@ class CSMShadowNode extends Node {
 
 	setupFade() {
 
-		const cameraNear = reference( 'camera.near', 'float', this ).setGroup( renderGroup ).label( 'cameraNear' );
+		const cameraNear = reference( 'camera.near', 'float', this ).setGroup( renderGroup );
 		const cascades = reference( '_cascades', 'vec2', this ).setGroup( renderGroup ).label( 'cacades' );
 
 		const shadowFar = uniform( 'float' ).setGroup( renderGroup ).label( 'shadowFar' )
@@ -327,7 +329,7 @@ class CSMShadowNode extends Node {
 
 	setupStandard() {
 
-		const cameraNear = reference( 'camera.near', 'float', this ).setGroup( renderGroup ).label( 'cameraNear' );
+		const cameraNear = reference( 'camera.near', 'float', this ).setGroup( renderGroup );
 		const cascades = reference( '_cascades', 'vec2', this ).setGroup( renderGroup ).label( 'cacades' );
 
 		const shadowFar = uniform( 'float' ).setGroup( renderGroup ).label( 'shadowFar' )

+ 5 - 1
examples/jsm/geometries/DecalGeometry.js

@@ -1,8 +1,10 @@
 import {
 	BufferGeometry,
+	Euler,
 	Float32BufferAttribute,
 	Matrix3,
 	Matrix4,
+	Mesh,
 	Vector3
 } from 'three';
 
@@ -23,7 +25,7 @@ import {
 
 class DecalGeometry extends BufferGeometry {
 
-	constructor( mesh, position, orientation, size ) {
+	constructor( mesh = new Mesh(), position = new Vector3(), orientation = new Euler(), size = new Vector3( 1, 1, 1 ) ) {
 
 		super();
 
@@ -109,6 +111,8 @@ class DecalGeometry extends BufferGeometry {
 
 			} else {
 
+				if ( positionAttribute === undefined ) return; // empty geometry
+
 				// non-indexed BufferGeometry
 
 				for ( let i = 0; i < positionAttribute.count; i ++ ) {

+ 1 - 1
examples/jsm/lighting/TiledLighting.js

@@ -1,4 +1,4 @@
-import { Lighting } from 'three';
+import { Lighting } from 'three/webgpu';
 import { tiledLights } from '../tsl/lighting/TiledLightsNode.js';
 
 export class TiledLighting extends Lighting {

+ 25 - 0
examples/jsm/lines/LineGeometry.js

@@ -62,6 +62,31 @@ class LineGeometry extends LineSegmentsGeometry {
 
 	}
 
+	setFromPoints( points ) {
+
+		// converts a vector3 or vector2 array to pairs format
+
+		const length = points.length - 1;
+		const positions = new Float32Array( 6 * length );
+
+		for ( let i = 0; i < length; i ++ ) {
+
+			positions[ 6 * i ] = points[ i ].x;
+			positions[ 6 * i + 1 ] = points[ i ].y;
+			positions[ 6 * i + 2 ] = points[ i ].z || 0;
+
+			positions[ 6 * i + 3 ] = points[ i + 1 ].x;
+			positions[ 6 * i + 4 ] = points[ i + 1 ].y;
+			positions[ 6 * i + 5 ] = points[ i + 1 ].z || 0;
+
+		}
+
+		super.setPositions( positions );
+
+		return this;
+
+	}
+
 	fromLine( line ) {
 
 		const geometry = line.geometry;

+ 1 - 7
examples/jsm/lines/LineMaterial.js

@@ -405,17 +405,11 @@ ShaderLib[ 'line' ] = {
 
 class LineMaterial extends ShaderMaterial {
 
-
-	static get type() {
-
-		return 'LineMaterial';
-
-	}
-
 	constructor( parameters ) {
 
 		super( {
 
+			type: 'LineMaterial',
 			uniforms: UniformsUtils.clone( ShaderLib[ 'line' ].uniforms ),
 
 			vertexShader: ShaderLib[ 'line' ].vertexShader,

+ 2 - 1
examples/jsm/lines/webgpu/Line2.js

@@ -1,7 +1,8 @@
+import { Line2NodeMaterial } from 'three/webgpu';
+
 import { LineSegments2 } from './LineSegments2.js';
 import { LineGeometry } from '../LineGeometry.js';
 
-import { Line2NodeMaterial } from 'three';
 
 class Line2 extends LineSegments2 {
 

+ 2 - 1
examples/jsm/lines/webgpu/LineSegments2.js

@@ -10,7 +10,8 @@ import {
 	Vector3,
 	Vector4,
 	Line2NodeMaterial
-} from 'three';
+} from 'three/webgpu';
+
 import { LineSegmentsGeometry } from '../../lines/LineSegmentsGeometry.js';
 
 const _start = new Vector3();

+ 2 - 1
examples/jsm/lines/webgpu/Wireframe.js

@@ -4,7 +4,8 @@ import {
 	Line2NodeMaterial,
 	Mesh,
 	Vector3
-} from 'three';
+} from 'three/webgpu';
+
 import { LineSegmentsGeometry } from '../../lines/LineSegmentsGeometry.js';
 
 const _start = new Vector3();

+ 3 - 0
examples/jsm/loaders/KTX2Loader.js

@@ -988,6 +988,9 @@ async function createRawTexture( container ) {
 
 		texture = new CompressedTexture( mipmaps, container.pixelWidth, container.pixelHeight );
 
+		texture.minFilter = mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter;
+		texture.magFilter = LinearFilter;
+
 	}
 
 	texture.mipmaps = mipmaps;

+ 2 - 6
examples/jsm/loaders/MMDLoader.js

@@ -2131,18 +2131,14 @@ class CubicBezierInterpolation extends Interpolant {
 
 class MMDToonMaterial extends ShaderMaterial {
 
-	static get type() {
-
-		return 'MMDToonMaterial';
-
-	}
-
 	constructor( parameters ) {
 
 		super();
 
 		this.isMMDToonMaterial = true;
 
+		this.type = 'MMDToonMaterial';
+
 		this._matcapCombine = AddOperation;
 		this.emissiveIntensity = 1.0;
 		this.normalMapType = TangentSpaceNormalMap;

+ 2 - 2
examples/jsm/loaders/MaterialXLoader.js

@@ -1,4 +1,4 @@
-import { FileLoader, Loader, TextureLoader, MeshBasicNodeMaterial, MeshPhysicalNodeMaterial, RepeatWrapping } from 'three';
+import { FileLoader, Loader, TextureLoader, RepeatWrapping, MeshBasicNodeMaterial, MeshPhysicalNodeMaterial } from 'three/webgpu';
 
 import {
 	float, bool, int, vec2, vec3, vec4, color, texture,
@@ -396,7 +396,7 @@ class MaterialXNode {
 
 		} else if ( this.hasReference ) {
 
-			if ( this.element === 'output' && this.output && out === null  ) {
+			if ( this.element === 'output' && this.output && out === null ) {
 
 				out = this.output;
 

+ 2 - 6
examples/jsm/materials/MeshGouraudMaterial.js

@@ -315,18 +315,14 @@ const GouraudShader = {
 
 class MeshGouraudMaterial extends ShaderMaterial {
 
-	static get type() {
-
-		return 'MeshGouraudMaterial';
-
-	}
-
 	constructor( parameters ) {
 
 		super();
 
 		this.isMeshGouraudMaterial = true;
 
+		this.type = 'MeshGouraudMaterial';
+
 		//this.color = new THREE.Color( 0xffffff ); // diffuse
 
 		//this.map = null;

+ 2 - 2
examples/jsm/misc/ProgressiveLightMapGPU.js

@@ -1,5 +1,5 @@
-import { DoubleSide, FloatType, HalfFloatType, PlaneGeometry, Mesh, RenderTarget, Scene } from 'three';
-import { add, float, mix, MeshPhongNodeMaterial, NodeMaterial, output, sub, texture, uniform, uv, vec2, vec4 } from 'three/tsl';
+import { DoubleSide, FloatType, HalfFloatType, PlaneGeometry, Mesh, RenderTarget, Scene, MeshPhongNodeMaterial, NodeMaterial } from 'three/webgpu';
+import { add, float, mix, output, sub, texture, uniform, uv, vec2, vec4 } from 'three/tsl';
 
 import { potpack } from '../libs/potpack.module.js';
 

+ 2 - 4
examples/jsm/objects/InstancedPoints.js

@@ -1,7 +1,5 @@
-import {
-	Mesh,
-	InstancedPointsNodeMaterial
-} from 'three';
+import { Mesh, InstancedPointsNodeMaterial } from 'three/webgpu';
+
 import InstancedPointsGeometry from '../geometries/InstancedPointsGeometry.js';
 
 class InstancedPoints extends Mesh {

+ 4 - 2
examples/jsm/objects/LensflareMesh.js

@@ -12,9 +12,11 @@ import {
 	UnsignedByteType,
 	Vector2,
 	Vector3,
-	Vector4 } from 'three';
+	Vector4,
+	Node
+} from 'three/webgpu';
 
-import { texture, textureLoad, uv, ivec2, vec2, vec4, positionGeometry, reference, varyingProperty, materialReference, Fn, Node } from 'three/tsl';
+import { texture, textureLoad, uv, ivec2, vec2, vec4, positionGeometry, reference, varyingProperty, materialReference, Fn } from 'three/tsl';
 
 class LensflareMesh extends Mesh {
 

+ 5 - 3
examples/jsm/objects/SkyMesh.js

@@ -2,9 +2,11 @@ import {
 	BackSide,
 	BoxGeometry,
 	Mesh,
-	Vector3
-} from 'three';
-import { Fn, NodeMaterial, float, vec3, acos, add, mul, clamp, cos, dot, exp, max, mix, modelViewProjection, normalize, positionWorld, pow, smoothstep, sub, varying, varyingProperty, vec4, uniform, cameraPosition } from 'three/tsl';
+	Vector3,
+	NodeMaterial
+} from 'three/webgpu';
+
+import { Fn, float, vec3, acos, add, mul, clamp, cos, dot, exp, max, mix, modelViewProjection, normalize, positionWorld, pow, smoothstep, sub, varying, varyingProperty, vec4, uniform, cameraPosition } from 'three/tsl';
 
 /**
  * Based on "A Practical Analytic Model for Daylight"

+ 7 - 3
examples/jsm/objects/Water2Mesh.js

@@ -2,9 +2,13 @@ import {
 	Color,
 	Mesh,
 	Vector2,
-	Vector3
-} from 'three';
-import { Fn, NodeMaterial, NodeUpdateType, TempNode, vec2, viewportSafeUV, viewportSharedTexture, reflector, pow, float, abs, texture, uniform, vec4, cameraPosition, positionWorld, uv, mix, vec3, normalize, max, dot, screenUV } from 'three/tsl';
+	Vector3,
+	NodeMaterial,
+	NodeUpdateType,
+	TempNode
+} from 'three/webgpu';
+
+import { Fn, vec2, viewportSafeUV, viewportSharedTexture, reflector, pow, float, abs, texture, uniform, vec4, cameraPosition, positionWorld, uv, mix, vec3, normalize, max, dot, screenUV } from 'three/tsl';
 
 /**
  * References:

+ 5 - 3
examples/jsm/objects/WaterMesh.js

@@ -1,9 +1,11 @@
 import {
 	Color,
 	Mesh,
-	Vector3
-} from 'three';
-import { Fn, NodeMaterial, add, cameraPosition, div, normalize, positionWorld, sub, time, texture, vec2, vec3, vec4, max, dot, reflect, pow, length, float, uniform, reflector, mul, mix } from 'three/tsl';
+	Vector3,
+	NodeMaterial
+} from 'three/webgpu';
+
+import { Fn, add, cameraPosition, div, normalize, positionWorld, sub, time, texture, vec2, vec3, vec4, max, dot, reflect, pow, length, float, uniform, reflector, mul, mix } from 'three/tsl';
 
 /**
  * Work based on :

+ 2 - 2
examples/jsm/transpiler/AST.js

@@ -242,9 +242,9 @@ export class DynamicElement {
 
 export class AccessorElements {
 
-	constructor( property, elements = [] ) {
+	constructor( object, elements = [] ) {
 
-		this.property = property;
+		this.object = object;
 		this.elements = elements;
 
 		this.isAccessorElements = true;

+ 57 - 25
examples/jsm/transpiler/GLSLDecoder.js

@@ -30,6 +30,10 @@ const associativityRightToLeft = [
 	':'
 ];
 
+const glslToTSL = {
+	inversesqrt: 'inverseSqrt'
+};
+
 const spaceRegExp = /^((\t| )\n*)+/;
 const lineRegExp = /^\n+/;
 const commentRegExp = /^\/\*[\s\S]*?\*\//;
@@ -46,6 +50,12 @@ const operatorsRegExp = new RegExp( '^(\\' + [
 	'.', ',', ';', '!', '=', '~', '*', '/', '%', '+', '-', '<', '>', '&', '^', '|', '?', ':', '#'
 ].join( '$' ).split( '' ).join( '\\' ).replace( /\\\$/g, '|' ) + ')' );
 
+function getFunctionName( str ) {
+
+	return glslToTSL[ str ] || str;
+
+}
+
 function getGroupDelta( str ) {
 
 	if ( str === '(' || str === '[' || str === '{' ) return 1;
@@ -485,62 +495,84 @@ class GLSLDecoder {
 
 					// function call
 
-					const paramsTokens = this.parseFunctionParametersFromTokens( tokens.slice( 2, tokens.length - 1 ) );
+					const internalTokens = this.getTokensUntil( ')', tokens, 1 ).slice( 1, - 1 );
+
+					const paramsTokens = this.parseFunctionParametersFromTokens( internalTokens );
+
+					const functionCall = new FunctionCall( getFunctionName( firstToken.str ), paramsTokens );
+
+					const accessTokens = tokens.slice( 3 + internalTokens.length );
 
-					return new FunctionCall( firstToken.str, paramsTokens );
+					if ( accessTokens.length > 0 ) {
+
+						const elements = this.parseAccessorElementsFromTokens( accessTokens );
+
+						return new AccessorElements( functionCall, elements );
+
+					}
+
+					return functionCall;
 
 				} else if ( secondToken.str === '[' ) {
 
 					// array accessor
 
-					const elements = [];
+					const elements = this.parseAccessorElementsFromTokens( tokens.slice( 1 ) );
 
-					let currentTokens = tokens.slice( 1 );
+					return new AccessorElements( new Accessor( firstToken.str ), elements );
 
-					while ( currentTokens.length > 0 ) {
+				}
 
-						const token = currentTokens[ 0 ];
+			}
 
-						if ( token.str === '[' ) {
+			return new Accessor( firstToken.str );
 
-							const accessorTokens = this.getTokensUntil( ']', currentTokens );
+		}
 
-							const element = this.parseExpressionFromTokens( accessorTokens.slice( 1, accessorTokens.length - 1 ) );
+	}
 
-							currentTokens = currentTokens.slice( accessorTokens.length );
+	parseAccessorElementsFromTokens( tokens ) {
 
-							elements.push( new DynamicElement( element ) );
+		const elements = [];
 
-						} else if ( token.str === '.' ) {
+		let currentTokens = tokens;
 
-							const accessorTokens = currentTokens.slice( 1, 2 );
+		while ( currentTokens.length > 0 ) {
 
-							const element = this.parseExpressionFromTokens( accessorTokens );
+			const token = currentTokens[ 0 ];
 
-							currentTokens = currentTokens.slice( 2 );
+			if ( token.str === '[' ) {
 
-							elements.push( new StaticElement( element ) );
+				const accessorTokens = this.getTokensUntil( ']', currentTokens );
 
-						} else {
+				const element = this.parseExpressionFromTokens( accessorTokens.slice( 1, accessorTokens.length - 1 ) );
 
-							console.error( 'Unknown accessor expression', token );
+				currentTokens = currentTokens.slice( accessorTokens.length );
 
-							break;
+				elements.push( new DynamicElement( element ) );
 
-						}
+			} else if ( token.str === '.' ) {
 
-					}
+				const accessorTokens = currentTokens.slice( 1, 2 );
 
-					return new AccessorElements( firstToken.str, elements );
+				const element = this.parseExpressionFromTokens( accessorTokens );
 
-				}
+				currentTokens = currentTokens.slice( 2 );
 
-			}
+				elements.push( new StaticElement( element ) );
 
-			return new Accessor( firstToken.str );
+			} else {
+
+				console.error( 'Unknown accessor expression', token );
+
+				break;
+
+			}
 
 		}
 
+		return elements;
+
 	}
 
 	parseFunctionParametersFromTokens( tokens ) {

+ 11 - 6
examples/jsm/transpiler/TSLEncoder.js

@@ -1,4 +1,5 @@
-import * as THREE from 'three';
+import { REVISION } from 'three/webgpu';
+import * as TSL from 'three/tsl';
 
 import { VariableDeclaration, Accessor } from './AST.js';
 
@@ -43,7 +44,7 @@ const unaryLib = {
 	'--': 'decrement' // decrementBefore
 };
 
-const isPrimitive = ( value ) => /^(true|false|-?\d)/.test( value );
+const isPrimitive = ( value ) => /^(true|false|-?(\d|\.\d))/.test( value );
 
 class TSLEncoder {
 
@@ -68,7 +69,7 @@ class TSLEncoder {
 
 		name = name.split( '.' )[ 0 ];
 
-		if ( THREE[ name ] !== undefined && this.global.has( name ) === false && this._currentProperties[ name ] === undefined ) {
+		if ( TSL[ name ] !== undefined && this.global.has( name ) === false && this._currentProperties[ name ] === undefined ) {
 
 			this.imports.add( name );
 
@@ -158,6 +159,10 @@ class TSLEncoder {
 
 				this.addImport( opFn );
 
+			} else if ( opFn === '.' ) {
+
+				code = left + opFn + right;
+
 			} else {
 
 				code = left + '.' + opFn + '( ' + right + ' )';
@@ -192,7 +197,7 @@ class TSLEncoder {
 
 		} else if ( node.isAccessorElements ) {
 
-			code = node.property;
+			code = this.emitExpression( node.object );
 
 			for ( const element of node.elements ) {
 
@@ -248,7 +253,7 @@ class TSLEncoder {
 
 		} else if ( node.isUnary && node.expression.isNumber ) {
 
-			code = node.type + ' ' + node.expression.value;
+			code = node.expression.type + '( ' + node.type + ' ' + node.expression.value + ' )';
 
 		} else if ( node.isUnary ) {
 
@@ -690,7 +695,7 @@ ${ this.tab }} )`;
 		const imports = [ ...this.imports ];
 		const exports = [ ...this.global ];
 
-		let header = '// Three.js Transpiler r' + THREE.REVISION + '\n\n';
+		let header = '// Three.js Transpiler r' + REVISION + '\n\n';
 		let footer = '';
 
 		if ( this.iife ) {

+ 3 - 3
examples/jsm/tsl/display/AfterImageNode.js

@@ -1,5 +1,5 @@
-import { RenderTarget, Vector2, PostProcessingUtils } from 'three';
-import { TempNode, nodeObject, Fn, float, vec4, NodeUpdateType, uv, texture, passTexture, uniform, sign, max, convertToTexture, QuadMesh, NodeMaterial } from 'three/tsl';
+import { RenderTarget, Vector2, QuadMesh, NodeMaterial, PostProcessingUtils, TempNode, NodeUpdateType } from 'three/webgpu';
+import { nodeObject, Fn, float, vec4, uv, texture, passTexture, uniform, sign, max, convertToTexture } from 'three/tsl';
 
 const _size = /*@__PURE__*/ new Vector2();
 const _quadMeshComp = /*@__PURE__*/ new QuadMesh();
@@ -16,7 +16,7 @@ class AfterImageNode extends TempNode {
 
 	constructor( textureNode, damp = 0.96 ) {
 
-		super( textureNode );
+		super( 'vec4' );
 
 		this.textureNode = textureNode;
 		this.textureNodeOld = texture();

+ 2 - 2
examples/jsm/tsl/display/AnaglyphPassNode.js

@@ -1,5 +1,5 @@
-import { Matrix3 } from 'three';
-import { clamp, nodeObject, Fn, vec4, uv, uniform, max, NodeMaterial } from 'three/tsl';
+import { Matrix3, NodeMaterial } from 'three/webgpu';
+import { clamp, nodeObject, Fn, vec4, uv, uniform, max } from 'three/tsl';
 import StereoCompositePassNode from './StereoCompositePassNode.js';
 
 class AnaglyphPassNode extends StereoCompositePassNode {

+ 2 - 2
examples/jsm/tsl/display/AnamorphicNode.js

@@ -1,5 +1,5 @@
-import { RenderTarget, Vector2, PostProcessingUtils } from 'three';
-import { TempNode, nodeObject, Fn, float, NodeUpdateType, uv, passTexture, uniform, convertToTexture, QuadMesh, NodeMaterial, vec2, vec3, Loop, threshold } from 'three/tsl';
+import { RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, PostProcessingUtils } from 'three/webgpu';
+import { nodeObject, Fn, float, NodeUpdateType, uv, passTexture, uniform, convertToTexture, vec2, vec3, Loop, threshold } from 'three/tsl';
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 

+ 3 - 3
examples/jsm/tsl/display/BloomNode.js

@@ -1,5 +1,5 @@
-import { HalfFloatType, RenderTarget, Vector2, Vector3, PostProcessingUtils } from 'three';
-import { TempNode, nodeObject, Fn, float, NodeUpdateType, uv, passTexture, uniform, QuadMesh, NodeMaterial, Loop, texture, luminance, smoothstep, mix, vec4, uniformArray, add, int } from 'three/tsl';
+import { HalfFloatType, RenderTarget, Vector2, Vector3, TempNode, QuadMesh, NodeMaterial, PostProcessingUtils, NodeUpdateType } from 'three/webgpu';
+import { nodeObject, Fn, float, uv, passTexture, uniform, Loop, texture, luminance, smoothstep, mix, vec4, uniformArray, add, int } from 'three/tsl';
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
@@ -19,7 +19,7 @@ class BloomNode extends TempNode {
 
 	constructor( inputNode, strength = 1, radius = 0, threshold = 0 ) {
 
-		super();
+		super( 'vec4' );
 
 		this.inputNode = inputNode;
 		this.strength = uniform( strength );

+ 48 - 12
examples/jsm/tsl/display/DenoiseNode.js

@@ -1,5 +1,6 @@
-import { Vector2, Vector3 } from 'three';
-import { getNormalFromDepth, getViewPosition, convertToTexture, TempNode, nodeObject, Fn, float, NodeUpdateType, uv, uniform, Loop, luminance, vec2, vec3, vec4, uniformArray, int, dot, max, pow, abs, If, textureSize, sin, cos, mat2, PI } from 'three/tsl';
+import { DataTexture, RepeatWrapping, Vector2, Vector3, TempNode } from 'three/webgpu';
+import { texture, getNormalFromDepth, getViewPosition, convertToTexture, nodeObject, Fn, float, NodeUpdateType, uv, uniform, Loop, luminance, vec2, vec3, vec4, uniformArray, int, dot, max, pow, abs, If, textureSize, sin, cos, mat2, PI } from 'three/tsl';
+import { SimplexNoise } from '../../math/SimplexNoise.js';
 
 class DenoiseNode extends TempNode {
 
@@ -9,26 +10,29 @@ class DenoiseNode extends TempNode {
 
 	}
 
-	constructor( textureNode, depthNode, normalNode, noiseNode, camera ) {
+	constructor( textureNode, depthNode, normalNode, camera ) {
 
-		super();
+		super( 'vec4' );
 
 		this.textureNode = textureNode;
 		this.depthNode = depthNode;
 		this.normalNode = normalNode;
-		this.noiseNode = noiseNode;
 
-		this.cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse );
+		this.noiseNode = texture( generateDefaultNoise() );
+
 		this.lumaPhi = uniform( 5 );
 		this.depthPhi = uniform( 5 );
 		this.normalPhi = uniform( 5 );
 		this.radius = uniform( 5 );
 		this.index = uniform( 0 );
 
+		this.updateBeforeType = NodeUpdateType.FRAME;
+
+		// uniforms
+
 		this._resolution = uniform( new Vector2() );
 		this._sampleVectors = uniformArray( generatePdSamplePointInitializer( 16, 2, 1 ) );
-
-		this.updateBeforeType = NodeUpdateType.FRAME;
+		this._cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse );
 
 	}
 
@@ -46,7 +50,7 @@ class DenoiseNode extends TempNode {
 
 		const sampleTexture = ( uv ) => this.textureNode.uv( uv );
 		const sampleDepth = ( uv ) => this.depthNode.uv( uv ).x;
-		const sampleNormal = ( uv ) => ( this.normalNode !== null ) ? this.normalNode.uv( uv ).rgb.normalize() : getNormalFromDepth( uv, this.depthNode.value, this.cameraProjectionMatrixInverse );
+		const sampleNormal = ( uv ) => ( this.normalNode !== null ) ? this.normalNode.uv( uv ).rgb.normalize() : getNormalFromDepth( uv, this.depthNode.value, this._cameraProjectionMatrixInverse );
 		const sampleNoise = ( uv ) => this.noiseNode.uv( uv );
 
 		const denoiseSample = Fn( ( [ center, viewNormal, viewPosition, sampleUv ] ) => {
@@ -55,7 +59,7 @@ class DenoiseNode extends TempNode {
 			const depth = sampleDepth( sampleUv ).toVar();
 			const normal = sampleNormal( sampleUv ).toVar();
 			const neighborColor = texel.rgb;
-			const viewPos = getViewPosition( sampleUv, depth, this.cameraProjectionMatrixInverse ).toVar();
+			const viewPos = getViewPosition( sampleUv, depth, this._cameraProjectionMatrixInverse ).toVar();
 
 			const normalDiff = dot( viewNormal, normal ).toVar();
 			const normalSimilarity = pow( max( normalDiff, 0 ), this.normalPhi ).toVar();
@@ -84,7 +88,7 @@ class DenoiseNode extends TempNode {
 
 			const center = vec3( texel.rgb ).toVar();
 
-			const viewPosition = getViewPosition( uvNode, depth, this.cameraProjectionMatrixInverse ).toVar();
+			const viewPosition = getViewPosition( uvNode, depth, this._cameraProjectionMatrixInverse ).toVar();
 
 			const noiseResolution = textureSize( this.noiseNode, 0 );
 			let noiseUv = vec2( uvNode.x, uvNode.y.oneMinus() );
@@ -178,4 +182,36 @@ function generateDenoiseSamples( numSamples, numRings, radiusExponent ) {
 
 }
 
-export const denoise = ( node, depthNode, normalNode, noiseNode, camera ) => nodeObject( new DenoiseNode( convertToTexture( node ), nodeObject( depthNode ), nodeObject( normalNode ), nodeObject( noiseNode ), camera ) );
+function generateDefaultNoise( size = 64 ) {
+
+	const simplex = new SimplexNoise();
+
+	const arraySize = size * size * 4;
+	const data = new Uint8Array( arraySize );
+
+	for ( let i = 0; i < size; i ++ ) {
+
+		for ( let j = 0; j < size; j ++ ) {
+
+			const x = i;
+			const y = j;
+
+			data[ ( i * size + j ) * 4 ] = ( simplex.noise( x, y ) * 0.5 + 0.5 ) * 255;
+			data[ ( i * size + j ) * 4 + 1 ] = ( simplex.noise( x + size, y ) * 0.5 + 0.5 ) * 255;
+			data[ ( i * size + j ) * 4 + 2 ] = ( simplex.noise( x, y + size ) * 0.5 + 0.5 ) * 255;
+			data[ ( i * size + j ) * 4 + 3 ] = ( simplex.noise( x + size, y + size ) * 0.5 + 0.5 ) * 255;
+
+		}
+
+	}
+
+	const noiseTexture = new DataTexture( data, size, size );
+	noiseTexture.wrapS = RepeatWrapping;
+	noiseTexture.wrapT = RepeatWrapping;
+	noiseTexture.needsUpdate = true;
+
+	return noiseTexture;
+
+}
+
+export const denoise = ( node, depthNode, normalNode, camera ) => nodeObject( new DenoiseNode( convertToTexture( node ), nodeObject( depthNode ), nodeObject( normalNode ), camera ) );

+ 3 - 2
examples/jsm/tsl/display/DepthOfFieldNode.js

@@ -1,4 +1,5 @@
-import { convertToTexture, TempNode, nodeObject, Fn, NodeUpdateType, uv, uniform, vec2, vec4, clamp } from 'three/tsl';
+import { TempNode, NodeUpdateType } from 'three/webgpu';
+import { convertToTexture, nodeObject, Fn, uv, uniform, vec2, vec4, clamp } from 'three/tsl';
 
 class DepthOfFieldNode extends TempNode {
 
@@ -10,7 +11,7 @@ class DepthOfFieldNode extends TempNode {
 
 	constructor( textureNode, viewZNode, focusNode, apertureNode, maxblurNode ) {
 
-		super();
+		super( 'vec4' );
 
 		this.textureNode = textureNode;
 		this.viewZNode = viewZNode;

+ 2 - 2
examples/jsm/tsl/display/DotScreenNode.js

@@ -1,5 +1,5 @@
-import { Vector2 } from 'three';
-import { TempNode, nodeObject, Fn, uv, uniform, vec2, vec3, sin, cos, add, vec4, screenSize } from 'three/tsl';
+import { Vector2, TempNode } from 'three/webgpu';
+import { nodeObject, Fn, uv, uniform, vec2, vec3, sin, cos, add, vec4, screenSize } from 'three/tsl';
 
 class DotScreenNode extends TempNode {
 

+ 3 - 3
examples/jsm/tsl/display/FXAANode.js

@@ -1,5 +1,5 @@
-import { Vector2 } from 'three';
-import { TempNode, nodeObject, Fn, uniformArray, select, float, NodeUpdateType, uv, dot, clamp, uniform, convertToTexture, smoothstep, bool, vec2, vec3, If, Loop, max, min, Break, abs } from 'three/tsl';
+import { Vector2, TempNode } from 'three/webgpu';
+import { nodeObject, Fn, uniformArray, select, float, NodeUpdateType, uv, dot, clamp, uniform, convertToTexture, smoothstep, bool, vec2, vec3, If, Loop, max, min, Break, abs } from 'three/tsl';
 
 class FXAANode extends TempNode {
 
@@ -11,7 +11,7 @@ class FXAANode extends TempNode {
 
 	constructor( textureNode ) {
 
-		super();
+		super( 'vec4' );
 
 		this.textureNode = textureNode;
 

+ 3 - 2
examples/jsm/tsl/display/FilmNode.js

@@ -1,4 +1,5 @@
-import { TempNode, rand, Fn, fract, time, uv, clamp, mix, vec4, nodeProxy } from 'three/tsl';
+import { TempNode } from 'three/webgpu';
+import { rand, Fn, fract, time, uv, clamp, mix, vec4, nodeProxy } from 'three/tsl';
 
 class FilmNode extends TempNode {
 
@@ -10,7 +11,7 @@ class FilmNode extends TempNode {
 
 	constructor( inputNode, intensityNode = null, uvNode = null ) {
 
-		super();
+		super( 'vec4' );
 
 		this.inputNode = inputNode;
 		this.intensityNode = intensityNode;

+ 62 - 27
examples/jsm/tsl/display/GTAONode.js

@@ -1,11 +1,15 @@
-import { DataTexture, RenderTarget, RepeatWrapping, Vector2, Vector3, PostProcessingUtils } from 'three';
-import { getNormalFromDepth, getScreenPosition, getViewPosition, QuadMesh, TempNode, nodeObject, Fn, float, NodeUpdateType, uv, uniform, Loop, vec2, vec3, vec4, int, dot, max, pow, abs, If, textureSize, sin, cos, PI, texture, passTexture, mat3, add, normalize, mul, cross, div, mix, sqrt, sub, acos, clamp, NodeMaterial } from 'three/tsl';
+import { DataTexture, RenderTarget, RepeatWrapping, Vector2, Vector3, TempNode, QuadMesh, NodeMaterial, PostProcessingUtils } from 'three/webgpu';
+import { reference, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getNormalFromDepth, getScreenPosition, getViewPosition, nodeObject, Fn, float, NodeUpdateType, uv, uniform, Loop, vec2, vec3, vec4, int, dot, max, pow, abs, If, textureSize, sin, cos, PI, texture, passTexture, mat3, add, normalize, mul, cross, div, mix, sqrt, sub, acos, clamp } from 'three/tsl';
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
 
 let _rendererState;
 
+/**
+ * References:
+ * https://www.activision.com/cdn/research/Practical_Real_Time_Strategies_for_Accurate_Indirect_Occlusion_NEW%20VERSION_COLOR.pdf
+ */
 class GTAONode extends TempNode {
 
 	static get type() {
@@ -16,31 +20,44 @@ class GTAONode extends TempNode {
 
 	constructor( depthNode, normalNode, camera ) {
 
-		super();
+		super( 'vec4' );
 
 		this.depthNode = depthNode;
 		this.normalNode = normalNode;
 
+		this.resolutionScale = 1;
+
+		this.updateBeforeType = NodeUpdateType.FRAME;
+
+		// render targets
+
+		this._aoRenderTarget = new RenderTarget( 1, 1, { depthBuffer: false } );
+		this._aoRenderTarget.texture.name = 'GTAONode.AO';
+
+		// uniforms
+
 		this.radius = uniform( 0.25 );
 		this.resolution = uniform( new Vector2() );
 		this.thickness = uniform( 1 );
 		this.distanceExponent = uniform( 1 );
 		this.distanceFallOff = uniform( 1 );
 		this.scale = uniform( 1 );
-		this.noiseNode = texture( generateMagicSquareNoise() );
+		this.samples = uniform( 16 );
 
-		this.cameraProjectionMatrix = uniform( camera.projectionMatrix );
-		this.cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse );
+		this._noiseNode = texture( generateMagicSquareNoise() );
+		this._cameraProjectionMatrix = uniform( camera.projectionMatrix );
+		this._cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse );
+		this._cameraNear = reference( 'near', 'float', camera );
+		this._cameraFar = reference( 'far', 'float', camera );
 
-		this.SAMPLES = uniform( 16 );
+		// materials
 
-		this._aoRenderTarget = new RenderTarget( 1, 1, { depthBuffer: false } );
-		this._aoRenderTarget.texture.name = 'GTAONode.AO';
+		this._material = new NodeMaterial();
+		this._material.name = 'GTAO';
 
-		this._material = null;
-		this._textureNode = passTexture( this, this._aoRenderTarget.texture );
+		//
 
-		this.updateBeforeType = NodeUpdateType.FRAME;
+		this._textureNode = passTexture( this, this._aoRenderTarget.texture );
 
 	}
 
@@ -52,6 +69,9 @@ class GTAONode extends TempNode {
 
 	setSize( width, height ) {
 
+		width = Math.round( this.resolutionScale * width );
+		height = Math.round( this.resolutionScale * height );
+
 		this.resolution.value.set( width, height );
 		this._aoRenderTarget.setSize( width, height );
 
@@ -89,9 +109,24 @@ class GTAONode extends TempNode {
 
 		const uvNode = uv();
 
-		const sampleDepth = ( uv ) => this.depthNode.uv( uv ).x;
-		const sampleNoise = ( uv ) => this.noiseNode.uv( uv );
-		const sampleNormal = ( uv ) => ( this.normalNode !== null ) ? this.normalNode.uv( uv ).rgb.normalize() : getNormalFromDepth( uv, this.depthNode.value, this.cameraProjectionMatrixInverse );
+		const sampleDepth = ( uv ) => {
+
+			const depth = this.depthNode.uv( uv ).r;
+
+			if ( builder.renderer.logarithmicDepthBuffer === true ) {
+
+				const viewZ = logarithmicDepthToViewZ( depth, this._cameraNear, this._cameraFar );
+
+				return viewZToPerspectiveDepth( viewZ, this._cameraNear, this._cameraFar );
+
+			}
+
+			return depth;
+
+		};
+
+		const sampleNoise = ( uv ) => this._noiseNode.uv( uv );
+		const sampleNormal = ( uv ) => ( this.normalNode !== null ) ? this.normalNode.uv( uv ).rgb.normalize() : getNormalFromDepth( uv, this.depthNode.value, this._cameraProjectionMatrixInverse );
 
 		const ao = Fn( () => {
 
@@ -99,12 +134,12 @@ class GTAONode extends TempNode {
 
 			depth.greaterThanEqual( 1.0 ).discard();
 
-			const viewPosition = getViewPosition( uvNode, depth, this.cameraProjectionMatrixInverse ).toVar();
+			const viewPosition = getViewPosition( uvNode, depth, this._cameraProjectionMatrixInverse ).toVar();
 			const viewNormal = sampleNormal( uvNode ).toVar();
 
 			const radiusToUse = this.radius;
 
-			const noiseResolution = textureSize( this.noiseNode, 0 );
+			const noiseResolution = textureSize( this._noiseNode, 0 );
 			let noiseUv = vec2( uvNode.x, uvNode.y.oneMinus() );
 			noiseUv = noiseUv.mul( this.resolution.div( noiseResolution ) );
 			const noiseTexel = sampleNoise( noiseUv );
@@ -113,8 +148,8 @@ class GTAONode extends TempNode {
 			const bitangent = vec3( tangent.y.mul( - 1.0 ), tangent.x, 0.0 );
 			const kernelMatrix = mat3( tangent, bitangent, vec3( 0.0, 0.0, 1.0 ) );
 
-			const DIRECTIONS = this.SAMPLES.lessThan( 30 ).select( 3, 5 ).toVar();
-			const STEPS = add( this.SAMPLES, DIRECTIONS.sub( 1 ) ).div( DIRECTIONS ).toVar();
+			const DIRECTIONS = this.samples.lessThan( 30 ).select( 3, 5 ).toVar();
+			const STEPS = add( this.samples, DIRECTIONS.sub( 1 ) ).div( DIRECTIONS ).toVar();
 
 			const ao = float( 0 ).toVar();
 
@@ -138,9 +173,9 @@ class GTAONode extends TempNode {
 
 					// x
 
-					const sampleScreenPositionX = getScreenPosition( viewPosition.add( sampleViewOffset ), this.cameraProjectionMatrix ).toVar();
+					const sampleScreenPositionX = getScreenPosition( viewPosition.add( sampleViewOffset ), this._cameraProjectionMatrix ).toVar();
 					const sampleDepthX = sampleDepth( sampleScreenPositionX ).toVar();
-					const sampleSceneViewPositionX = getViewPosition( sampleScreenPositionX, sampleDepthX, this.cameraProjectionMatrixInverse ).toVar();
+					const sampleSceneViewPositionX = getViewPosition( sampleScreenPositionX, sampleDepthX, this._cameraProjectionMatrixInverse ).toVar();
 					const viewDeltaX = sampleSceneViewPositionX.sub( viewPosition ).toVar();
 
 					If( abs( viewDeltaX.z ).lessThan( this.thickness ), () => {
@@ -152,9 +187,9 @@ class GTAONode extends TempNode {
 
 					// y
 
-					const sampleScreenPositionY = getScreenPosition( viewPosition.sub( sampleViewOffset ), this.cameraProjectionMatrix ).toVar();
+					const sampleScreenPositionY = getScreenPosition( viewPosition.sub( sampleViewOffset ), this._cameraProjectionMatrix ).toVar();
 					const sampleDepthY = sampleDepth( sampleScreenPositionY ).toVar();
-					const sampleSceneViewPositionY = getViewPosition( sampleScreenPositionY, sampleDepthY, this.cameraProjectionMatrixInverse ).toVar();
+					const sampleSceneViewPositionY = getViewPosition( sampleScreenPositionY, sampleDepthY, this._cameraProjectionMatrixInverse ).toVar();
 					const viewDeltaY = sampleSceneViewPositionY.sub( viewPosition ).toVar();
 
 					If( abs( viewDeltaY.z ).lessThan( this.thickness ), () => {
@@ -183,10 +218,8 @@ class GTAONode extends TempNode {
 
 		} );
 
-		const material = this._material || ( this._material = new NodeMaterial() );
-		material.fragmentNode = ao().context( builder.getSharedContext() );
-		material.name = 'GTAO';
-		material.needsUpdate = true;
+		this._material.fragmentNode = ao().context( builder.getSharedContext() );
+		this._material.needsUpdate = true;
 
 		//
 
@@ -198,6 +231,8 @@ class GTAONode extends TempNode {
 
 		this._aoRenderTarget.dispose();
 
+		this._material.dispose();
+
 	}
 
 }

+ 6 - 8
examples/jsm/tsl/display/GaussianBlurNode.js

@@ -1,11 +1,10 @@
-import { RenderTarget, Vector2, PostProcessingUtils } from 'three';
-import { TempNode, nodeObject, Fn, If, float, NodeUpdateType, uv, uniform, convertToTexture, vec2, vec4, QuadMesh, passTexture, mul, NodeMaterial } from 'three/tsl';
+import { RenderTarget, Vector2, NodeMaterial, PostProcessingUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu';
+import { nodeObject, Fn, If, float, uv, uniform, convertToTexture, vec2, vec4, passTexture, mul } from 'three/tsl';
 
 // WebGPU: The use of a single QuadMesh for both gaussian blur passes results in a single RenderObject with a SampledTexture binding that
 // alternates between source textures and triggers creation of new BindGroups and BindGroupLayouts every frame.
 
-const _quadMesh1 = /*@__PURE__*/ new QuadMesh();
-const _quadMesh2 = /*@__PURE__*/ new QuadMesh();
+const _quadMesh = /*@__PURE__*/ new QuadMesh();
 
 let _rendererState;
 
@@ -108,8 +107,7 @@ class GaussianBlurNode extends TempNode {
 
 		const currentTexture = textureNode.value;
 
-		_quadMesh1.material = this._material;
-		_quadMesh2.material = this._material;
+		_quadMesh.material = this._material;
 
 		this.setSize( map.image.width, map.image.height );
 
@@ -124,7 +122,7 @@ class GaussianBlurNode extends TempNode {
 
 		this._passDirection.value.set( 1, 0 );
 
-		_quadMesh1.render( renderer );
+		_quadMesh.render( renderer );
 
 		// vertical
 
@@ -133,7 +131,7 @@ class GaussianBlurNode extends TempNode {
 
 		this._passDirection.value.set( 0, 1 );
 
-		_quadMesh2.render( renderer );
+		_quadMesh.render( renderer );
 
 		// restore
 

+ 3 - 3
examples/jsm/tsl/display/LensflareNode.js

@@ -1,5 +1,5 @@
-import { RenderTarget, Vector2 } from 'three';
-import { convertToTexture, TempNode, nodeObject, Fn, NodeUpdateType, QuadMesh, PostProcessingUtils, NodeMaterial, passTexture, uv, vec2, vec3, vec4, max, float, sub, int, Loop, fract, pow, distance } from 'three/tsl';
+import { RenderTarget, Vector2, TempNode, NodeUpdateType, QuadMesh, PostProcessingUtils, NodeMaterial } from 'three/webgpu';
+import { convertToTexture, nodeObject, Fn, passTexture, uv, vec2, vec3, vec4, max, float, sub, int, Loop, fract, pow, distance } from 'three/tsl';
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
@@ -20,7 +20,7 @@ class LensflareNode extends TempNode {
 
 	constructor( textureNode, params = {} ) {
 
-		super();
+		super( 'vec4' );
 
 		this.textureNode = textureNode;
 

+ 3 - 2
examples/jsm/tsl/display/Lut3DNode.js

@@ -1,4 +1,5 @@
-import { TempNode, nodeObject, Fn, float, uniform, vec3, vec4, mix } from 'three/tsl';
+import { TempNode } from 'three/webgpu';
+import { nodeObject, Fn, float, uniform, vec3, vec4, mix } from 'three/tsl';
 
 class Lut3DNode extends TempNode {
 
@@ -10,7 +11,7 @@ class Lut3DNode extends TempNode {
 
 	constructor( inputNode, lutNode, size, intensityNode ) {
 
-		super();
+		super( 'vec4' );
 
 		this.inputNode = inputNode;
 		this.lutNode = lutNode;

+ 2 - 2
examples/jsm/tsl/display/OutlineNode.js

@@ -1,5 +1,5 @@
-import { Color, DepthTexture, FloatType, RenderTarget, Vector2, PostProcessingUtils } from 'three';
-import { Loop, int, exp, min, float, mul, uv, vec2, vec3, Fn, textureSize, orthographicDepthToViewZ, QuadMesh, screenUV, TempNode, nodeObject, NodeUpdateType, uniform, vec4, NodeMaterial, passTexture, texture, perspectiveDepthToViewZ, positionView } from 'three/tsl';
+import { Color, DepthTexture, FloatType, RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, PostProcessingUtils, NodeUpdateType } from 'three/webgpu';
+import { Loop, int, exp, min, float, mul, uv, vec2, vec3, Fn, textureSize, orthographicDepthToViewZ, screenUV, nodeObject, uniform, vec4, passTexture, texture, perspectiveDepthToViewZ, positionView } from 'three/tsl';
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();

+ 2 - 1
examples/jsm/tsl/display/ParallaxBarrierPassNode.js

@@ -1,4 +1,5 @@
-import { nodeObject, Fn, vec4, uv, NodeMaterial, If, mod, screenCoordinate } from 'three/tsl';
+import { NodeMaterial } from 'three/webgpu';
+import { nodeObject, Fn, vec4, uv, If, mod, screenCoordinate } from 'three/tsl';
 import StereoCompositePassNode from './StereoCompositePassNode.js';
 
 class ParallaxBarrierPassNode extends StereoCompositePassNode {

+ 4 - 4
examples/jsm/tsl/display/PixelationPassNode.js

@@ -1,5 +1,5 @@
-import { NearestFilter, Vector4 } from 'three';
-import { TempNode, nodeObject, Fn, float, NodeUpdateType, uv, uniform, convertToTexture, vec2, vec3, clamp, floor, dot, smoothstep, If, sign, step, mrt, output, normalView, PassNode, property } from 'three/tsl';
+import { NearestFilter, Vector4, TempNode, NodeUpdateType, PassNode } from 'three/webgpu';
+import { nodeObject, Fn, float, uv, uniform, convertToTexture, vec2, vec3, clamp, floor, dot, smoothstep, If, sign, step, mrt, output, normalView, property } from 'three/tsl';
 
 class PixelationNode extends TempNode {
 
@@ -11,7 +11,7 @@ class PixelationNode extends TempNode {
 
 	constructor( textureNode, depthNode, normalNode, pixelSize, normalEdgeStrength, depthEdgeStrength ) {
 
-		super();
+		super( 'vec4' );
 
 		// Input textures
 
@@ -158,7 +158,7 @@ class PixelationPassNode extends PassNode {
 
 	constructor( scene, camera, pixelSize = 6, normalEdgeStrength = 0.3, depthEdgeStrength = 0.4 ) {
 
-		super( 'color', scene, camera, { minFilter: NearestFilter, magFilter: NearestFilter } );
+		super( PassNode.COLOR, scene, camera, { minFilter: NearestFilter, magFilter: NearestFilter } );
 
 		this.pixelSize = pixelSize;
 		this.normalEdgeStrength = normalEdgeStrength;

+ 2 - 1
examples/jsm/tsl/display/RGBShiftNode.js

@@ -1,4 +1,5 @@
-import { TempNode, nodeObject, Fn, uv, uniform, vec2, sin, cos, vec4, convertToTexture } from 'three/tsl';
+import { TempNode } from 'three/webgpu';
+import { nodeObject, Fn, uv, uniform, vec2, sin, cos, vec4, convertToTexture } from 'three/tsl';
 
 class RGBShiftNode extends TempNode {
 

+ 3 - 3
examples/jsm/tsl/display/SMAANode.js

@@ -1,5 +1,5 @@
-import { HalfFloatType, LinearFilter, NearestFilter, RenderTarget, Texture, Vector2, PostProcessingUtils } from 'three';
-import { abs, QuadMesh, NodeMaterial, TempNode, nodeObject, Fn, NodeUpdateType, uv, uniform, convertToTexture, varyingProperty, vec2, vec4, modelViewProjection, passTexture, max, step, dot, float, texture, If, Loop, int, Break, sqrt, sign, mix } from 'three/tsl';
+import { HalfFloatType, LinearFilter, NearestFilter, RenderTarget, Texture, Vector2, QuadMesh, NodeMaterial, TempNode, PostProcessingUtils } from 'three/webgpu';
+import { abs, nodeObject, Fn, NodeUpdateType, uv, uniform, convertToTexture, varyingProperty, vec2, vec4, modelViewProjection, passTexture, max, step, dot, float, texture, If, Loop, int, Break, sqrt, sign, mix } from 'three/tsl';
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
@@ -22,7 +22,7 @@ class SMAANode extends TempNode {
 
 	constructor( textureNode ) {
 
-		super();
+		super( 'vec4' );
 
 		this.textureNode = textureNode;
 

+ 2 - 2
examples/jsm/tsl/display/SSAAPassNode.js

@@ -1,5 +1,5 @@
-import { AdditiveBlending, Color, Vector2, PostProcessingUtils } from 'three';
-import { nodeObject, uniform, mrt, PassNode, QuadMesh, texture, NodeMaterial, getTextureIndex } from 'three/tsl';
+import { AdditiveBlending, Color, Vector2, PostProcessingUtils, PassNode, QuadMesh, NodeMaterial } from 'three/webgpu';
+import { nodeObject, uniform, mrt, texture, getTextureIndex } from 'three/tsl';
 
 const _size = /*@__PURE__*/ new Vector2();
 

+ 31 - 8
examples/jsm/tsl/display/SSRNode.js

@@ -1,5 +1,5 @@
-import { NearestFilter, RenderTarget, Vector2, PostProcessingUtils } from 'three';
-import { getScreenPosition, getViewPosition, sqrt, mul, div, cross, float, Continue, Break, Loop, int, max, abs, sub, If, dot, reflect, normalize, screenCoordinate, QuadMesh, TempNode, nodeObject, Fn, NodeUpdateType, passTexture, NodeMaterial, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, vec3, vec4 } from 'three/tsl';
+import { NearestFilter, RenderTarget, Vector2, PostProcessingUtils, QuadMesh, TempNode, NodeMaterial, NodeUpdateType } from 'three/webgpu';
+import { reference, viewZToPerspectiveDepth, logarithmicDepthToViewZ, getScreenPosition, getViewPosition, sqrt, mul, div, cross, float, Continue, Break, Loop, int, max, abs, sub, If, dot, reflect, normalize, screenCoordinate, nodeObject, Fn, passTexture, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, vec3, vec4 } from 'three/tsl';
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
@@ -19,7 +19,7 @@ class SSRNode extends TempNode {
 
 	constructor( colorNode, depthNode, normalNode, metalnessNode, camera ) {
 
-		super();
+		super( 'vec4' );
 
 		this.colorNode = colorNode;
 		this.depthNode = depthNode;
@@ -42,10 +42,10 @@ class SSRNode extends TempNode {
 		this.thickness = uniform( 0.1 ); // controls the cutoff between what counts as a possible reflection hit and what does not
 		this.opacity = uniform( 1 ); // controls the transparency of the reflected colors
 
-		this._cameraNear = uniform( camera.near );
-		this._cameraFar = uniform( camera.far );
 		this._cameraProjectionMatrix = uniform( camera.projectionMatrix );
 		this._cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse );
+		this._cameraNear = reference( 'near', 'float', camera );
+		this._cameraFar = reference( 'far', 'float', camera );
 		this._isPerspectiveCamera = uniform( camera.isPerspectiveCamera ? 1 : 0 );
 		this._resolution = uniform( new Vector2() );
 		this._maxStep = uniform( 0 );
@@ -151,15 +151,31 @@ class SSRNode extends TempNode {
 
 		} );
 
+		const sampleDepth = ( uv ) => {
+
+			const depth = this.depthNode.uv( uv ).r;
+
+			if ( builder.renderer.logarithmicDepthBuffer === true ) {
+
+				const viewZ = logarithmicDepthToViewZ( depth, this._cameraNear, this._cameraFar );
+
+				return viewZToPerspectiveDepth( viewZ, this._cameraNear, this._cameraFar );
+
+			}
+
+			return depth;
+
+		};
+
 		const ssr = Fn( () => {
 
 			const metalness = this.metalnessNode.uv( uvNode ).r;
 
-			 // fragments with no metalness do not reflect their environment
+			// fragments with no metalness do not reflect their environment
 			metalness.equal( 0.0 ).discard();
 
 			// compute some standard FX entities
-			const depth = this.depthNode.uv( uvNode ).r.toVar();
+			const depth = sampleDepth( uvNode ).toVar();
 			const viewPosition = getViewPosition( uvNode, depth, this._cameraProjectionMatrixInverse ).toVar();
 			const viewNormal = this.normalNode.rgb.normalize().toVar();
 
@@ -214,6 +230,13 @@ class SSRNode extends TempNode {
 			// it does not exceed d1 (the maximum ray extend)
 			Loop( { start: int( 0 ), end: int( this._maxStep ), type: 'int', condition: '<' }, ( { i } ) => {
 
+				// TODO: Remove this when Chrome is fixed, see https://issues.chromium.org/issues/372714384#comment14
+				If( metalness.equal( 0 ), () => {
+
+					Break();
+
+				} );
+
 				// stop if the maximum number of steps is reached for this specific ray
 				If( float( i ).greaterThanEqual( totalStep ), () => {
 
@@ -233,7 +256,7 @@ class SSRNode extends TempNode {
 
 				// compute new uv, depth, viewZ and viewPosition for the new location on the ray
 				const uvNode = xy.div( this._resolution );
-				const d = this.depthNode.uv( uvNode ).r.toVar();
+				const d = sampleDepth( uvNode ).toVar();
 				const vZ = getViewZ( d ).toVar();
 				const vP = getViewPosition( uvNode, d, this._cameraProjectionMatrixInverse ).toVar();
 

+ 3 - 3
examples/jsm/tsl/display/SobelOperatorNode.js

@@ -1,5 +1,5 @@
-import { Vector2 } from 'three';
-import { TempNode, nodeObject, Fn, NodeUpdateType, uv, uniform, convertToTexture, vec2, vec3, vec4, mat3, luminance, add } from 'three/tsl';
+import { Vector2, TempNode, NodeUpdateType } from 'three/webgpu';
+import { nodeObject, Fn, uv, uniform, convertToTexture, vec2, vec3, vec4, mat3, luminance, add } from 'three/tsl';
 
 class SobelOperatorNode extends TempNode {
 
@@ -11,7 +11,7 @@ class SobelOperatorNode extends TempNode {
 
 	constructor( textureNode ) {
 
-		super();
+		super( 'vec4' );
 
 		this.textureNode = textureNode;
 

+ 4 - 4
examples/jsm/tsl/display/StereoCompositePassNode.js

@@ -1,5 +1,5 @@
-import { RenderTarget, StereoCamera, HalfFloatType, LinearFilter, NearestFilter, Vector2, PostProcessingUtils } from 'three';
-import { PassNode, QuadMesh, texture } from 'three/tsl';
+import { RenderTarget, StereoCamera, HalfFloatType, LinearFilter, NearestFilter, Vector2, PassNode, QuadMesh, PostProcessingUtils } from 'three/webgpu';
+import { texture } from 'three/tsl';
 
 const _size = /*@__PURE__*/ new Vector2();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
@@ -55,7 +55,7 @@ class StereoCompositePassNode extends PassNode {
 		const { renderer } = frame;
 		const { scene, stereo, renderTarget } = this;
 
-		_rendererState = PostProcessingUtils.resetRendererAndSceneState( renderer, scene, _rendererState );
+		_rendererState = PostProcessingUtils.resetRendererState( renderer, _rendererState );
 
 		//
 
@@ -84,7 +84,7 @@ class StereoCompositePassNode extends PassNode {
 
 		// restore
 
-		PostProcessingUtils.restoreRendererState( renderer, scene, _rendererState );
+		PostProcessingUtils.restoreRendererState( renderer, _rendererState );
 
 	}
 

+ 2 - 2
examples/jsm/tsl/display/StereoPassNode.js

@@ -1,5 +1,5 @@
-import { StereoCamera, Vector2, PostProcessingUtils } from 'three';
-import { PassNode, nodeObject } from 'three/tsl';
+import { StereoCamera, Vector2, PassNode, PostProcessingUtils } from 'three/webgpu';
+import { nodeObject } from 'three/tsl';
 
 const _size = /*@__PURE__*/ new Vector2();
 

+ 2 - 2
examples/jsm/tsl/display/TRAAPassNode.js

@@ -1,5 +1,5 @@
-import { Color, Vector2, PostProcessingUtils, NearestFilter, Matrix4 } from 'three';
-import { add, float, If, Loop, int, Fn, min, max, clamp, nodeObject, PassNode, QuadMesh, texture, NodeMaterial, uniform, uv, vec2, vec4, luminance } from 'three/tsl';
+import { Color, Vector2, NearestFilter, Matrix4, PostProcessingUtils, PassNode, QuadMesh, NodeMaterial } from 'three/webgpu';
+import { add, float, If, Loop, int, Fn, min, max, clamp, nodeObject, texture, uniform, uv, vec2, vec4, luminance } from 'three/tsl';
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();

+ 3 - 2
examples/jsm/tsl/display/TransitionNode.js

@@ -1,4 +1,5 @@
-import { TempNode, nodeObject, Fn, float, uv, convertToTexture, vec4, If, int, clamp, sub, mix } from 'three/tsl';
+import { TempNode } from 'three/webgpu';
+import { nodeObject, Fn, float, uv, convertToTexture, vec4, If, int, clamp, sub, mix } from 'three/tsl';
 
 class TransitionNode extends TempNode {
 
@@ -10,7 +11,7 @@ class TransitionNode extends TempNode {
 
 	constructor( textureNodeA, textureNodeB, mixTextureNode, mixRatioNode, thresholdNode, useTextureNode ) {
 
-		super();
+		super( 'vec4' );
 
 		// Input textures
 

+ 6 - 9
examples/jsm/tsl/lighting/TiledLightsNode.js

@@ -1,10 +1,10 @@
+import { DataTexture, FloatType, RGBAFormat, Vector2, Vector3, LightsNode, NodeUpdateType } from 'three/webgpu';
+
 import {
-	storageObject, nodeProxy, int, float, vec2, ivec2, ivec4, uniform, Break, Loop,
+	attributeArray, nodeProxy, int, float, vec2, ivec2, ivec4, uniform, Break, Loop,
 	Fn, If, Return, textureLoad, instanceIndex, screenCoordinate, directPointLight
 } from 'three/tsl';
 
-import { DataTexture, FloatType, LightsNode, NodeUpdateType, RGBAFormat, StorageBufferAttribute, Vector2, Vector3 } from 'three';
-
 export const circleIntersectsAABB = /*@__PURE__*/ Fn( ( [ circleCenter, radius, minBounds, maxBounds ] ) => {
 
 	// Find the closest point on the AABB to the circle's center using method chaining
@@ -204,6 +204,8 @@ class TiledLightsNode extends LightsNode {
 		lightingModel.directDiffuse.append();
 		lightingModel.directSpecular.append();
 
+		super.setupLights( builder, lightNodes );
+
 		Fn( () => {
 
 			Loop( this.tileLightCount, ( { i } ) => {
@@ -229,10 +231,6 @@ class TiledLightsNode extends LightsNode {
 
 		} )().append();
 
-		// others lights
-
-		super.setupLights( builder, lightNodes );
-
 	}
 
 	getBufferFitSize( value ) {
@@ -291,8 +289,7 @@ class TiledLightsNode extends LightsNode {
 		const lightsTexture = new DataTexture( lightsData, lightsData.length / 8, 2, RGBAFormat, FloatType );
 
 		const lightIndexesArray = new Int32Array( count * 4 * 2 );
-		const lightIndexesAttribute = new StorageBufferAttribute( lightIndexesArray, 4 );
-		const lightIndexes = storageObject( lightIndexesAttribute, 'ivec4', lightIndexesAttribute.count ).label( 'lightIndexes' );
+		const lightIndexes = attributeArray( lightIndexesArray, 'ivec4' ).label( 'lightIndexes' );
 
 		// compute
 

+ 410 - 0
examples/jsm/utils/SceneOptimizer.js

@@ -0,0 +1,410 @@
+import * as THREE from 'three';
+
+class SceneOptimizer {
+
+	constructor( scene, options = {} ) {
+
+		this.scene = scene;
+		this.debug = options.debug || false;
+
+	}
+
+	bufferToHash( buffer ) {
+
+		let hash = 0;
+		if ( buffer.byteLength !== 0 ) {
+
+			let uintArray;
+			if ( buffer.buffer ) {
+
+				uintArray = new Uint8Array(
+					buffer.buffer,
+					buffer.byteOffset,
+					buffer.byteLength
+				);
+
+			} else {
+
+				uintArray = new Uint8Array( buffer );
+
+			}
+
+			for ( let i = 0; i < buffer.byteLength; i ++ ) {
+
+				const byte = uintArray[ i ];
+				hash = ( hash << 5 ) - hash + byte;
+				hash |= 0;
+
+			}
+
+		}
+
+		return hash;
+
+	}
+
+	getMaterialPropertiesHash( material ) {
+
+		const mapProps = [
+			'map',
+			'alphaMap',
+			'aoMap',
+			'bumpMap',
+			'displacementMap',
+			'emissiveMap',
+			'envMap',
+			'lightMap',
+			'metalnessMap',
+			'normalMap',
+			'roughnessMap',
+		];
+
+		const mapHash = mapProps
+			.map( ( prop ) => {
+
+				const map = material[ prop ];
+				if ( ! map ) return 0;
+				return `${map.uuid}_${map.offset.x}_${map.offset.y}_${map.repeat.x}_${map.repeat.y}_${map.rotation}`;
+
+			} )
+			.join( '|' );
+
+		const physicalProps = [
+			'transparent',
+			'opacity',
+			'alphaTest',
+			'alphaToCoverage',
+			'side',
+			'vertexColors',
+			'visible',
+			'blending',
+			'wireframe',
+			'flatShading',
+			'premultipliedAlpha',
+			'dithering',
+			'toneMapped',
+			'depthTest',
+			'depthWrite',
+			'metalness',
+			'roughness',
+			'clearcoat',
+			'clearcoatRoughness',
+			'sheen',
+			'sheenRoughness',
+			'transmission',
+			'thickness',
+			'attenuationDistance',
+			'ior',
+			'iridescence',
+			'iridescenceIOR',
+			'iridescenceThicknessRange',
+			'reflectivity',
+		]
+			.map( ( prop ) => {
+
+				if ( typeof material[ prop ] === 'undefined' ) return 0;
+				if ( material[ prop ] === null ) return 0;
+				return material[ prop ].toString();
+
+			} )
+			.join( '|' );
+
+		const emissiveHash = material.emissive ? material.emissive.getHexString() : 0;
+		const attenuationHash = material.attenuationColor
+			? material.attenuationColor.getHexString()
+			: 0;
+		const sheenColorHash = material.sheenColor
+			? material.sheenColor.getHexString()
+			: 0;
+
+		return [
+			material.type,
+			physicalProps,
+			mapHash,
+			emissiveHash,
+			attenuationHash,
+			sheenColorHash,
+		].join( '_' );
+
+	}
+
+	getAttributesSignature( geometry ) {
+
+		return Object.keys( geometry.attributes )
+			.sort()
+			.map( ( name ) => {
+
+				const attribute = geometry.attributes[ name ];
+				return `${name}_${attribute.itemSize}_${attribute.normalized}`;
+
+			} )
+			.join( '|' );
+
+	}
+
+	getGeometryHash( geometry ) {
+
+		const indexHash = geometry.index
+			? this.bufferToHash( geometry.index.array )
+			: 'noIndex';
+		const positionHash = this.bufferToHash( geometry.attributes.position.array );
+		const attributesSignature = this.getAttributesSignature( geometry );
+		return `${indexHash}_${positionHash}_${attributesSignature}`;
+
+	}
+
+	getBatchKey( materialProps, attributesSignature ) {
+
+		return `${materialProps}_${attributesSignature}`;
+
+	}
+
+	analyzeModel() {
+
+		const batchGroups = new Map();
+		const singleGroups = new Map();
+		const uniqueGeometries = new Set();
+
+		this.scene.updateMatrixWorld( true );
+		this.scene.traverse( ( node ) => {
+
+			if ( ! node.isMesh ) return;
+
+			const materialProps = this.getMaterialPropertiesHash( node.material );
+			const attributesSignature = this.getAttributesSignature( node.geometry );
+			const batchKey = this.getBatchKey( materialProps, attributesSignature );
+			const geometryHash = this.getGeometryHash( node.geometry );
+			uniqueGeometries.add( geometryHash );
+
+			if ( ! batchGroups.has( batchKey ) ) {
+
+				batchGroups.set( batchKey, {
+					meshes: [],
+					geometryStats: new Map(),
+					totalInstances: 0,
+					materialProps: node.material.clone(),
+				} );
+
+			}
+
+			const group = batchGroups.get( batchKey );
+			group.meshes.push( node );
+			group.totalInstances ++;
+
+			if ( ! group.geometryStats.has( geometryHash ) ) {
+
+				group.geometryStats.set( geometryHash, {
+					count: 0,
+					vertices: node.geometry.attributes.position.count,
+					indices: node.geometry.index ? node.geometry.index.count : 0,
+					geometry: node.geometry,
+				} );
+
+			}
+
+			group.geometryStats.get( geometryHash ).count ++;
+
+		} );
+
+		// Move single instance groups to singleGroups
+		for ( const [ batchKey, group ] of batchGroups ) {
+
+			if ( group.totalInstances === 1 ) {
+
+				singleGroups.set( batchKey, group );
+				batchGroups.delete( batchKey );
+
+			}
+
+		}
+
+		return { batchGroups, singleGroups, uniqueGeometries: uniqueGeometries.size };
+
+	}
+
+	createBatchedMeshes( batchGroups ) {
+
+		const meshesToRemove = new Set();
+
+		for ( const [ , group ] of batchGroups ) {
+
+			const maxGeometries = group.totalInstances;
+			const maxVertices = Array.from( group.geometryStats.values() ).reduce(
+				( sum, stats ) => sum + stats.vertices,
+				0
+			);
+			const maxIndices = Array.from( group.geometryStats.values() ).reduce(
+				( sum, stats ) => sum + stats.indices,
+				0
+			);
+
+			const batchedMaterial = new group.materialProps.constructor( group.materialProps );
+
+			if ( batchedMaterial.color !== undefined ) {
+
+				// Reset color to white, color will be set per instance
+				batchedMaterial.color.set( 1, 1, 1 );
+
+			}
+
+			const batchedMesh = new THREE.BatchedMesh(
+				maxGeometries,
+				maxVertices,
+				maxIndices,
+				batchedMaterial
+			);
+
+			const referenceMesh = group.meshes[ 0 ];
+			batchedMesh.name = `${referenceMesh.name}_batch`;
+
+			const geometryIds = new Map();
+			const inverseParentMatrix = new THREE.Matrix4();
+
+			if ( referenceMesh.parent ) {
+
+				referenceMesh.parent.updateWorldMatrix( true, false );
+				inverseParentMatrix.copy( referenceMesh.parent.matrixWorld ).invert();
+
+			}
+
+			for ( const mesh of group.meshes ) {
+
+				const geometryHash = this.getGeometryHash( mesh.geometry );
+
+				if ( ! geometryIds.has( geometryHash ) ) {
+
+					geometryIds.set( geometryHash, batchedMesh.addGeometry( mesh.geometry ) );
+
+				}
+
+				const geometryId = geometryIds.get( geometryHash );
+				const instanceId = batchedMesh.addInstance( geometryId );
+
+				const localMatrix = new THREE.Matrix4();
+				mesh.updateWorldMatrix( true, false );
+				localMatrix.copy( mesh.matrixWorld );
+				if ( referenceMesh.parent ) {
+
+					localMatrix.premultiply( inverseParentMatrix );
+
+				}
+
+				batchedMesh.setMatrixAt( instanceId, localMatrix );
+				batchedMesh.setColorAt( instanceId, mesh.material.color );
+
+				meshesToRemove.add( mesh );
+
+			}
+
+			if ( referenceMesh.parent ) {
+
+				referenceMesh.parent.add( batchedMesh );
+
+			}
+
+		}
+
+		return meshesToRemove;
+
+	}
+
+	removeEmptyNodes( object ) {
+
+		const children = [ ...object.children ];
+
+		for ( const child of children ) {
+
+			this.removeEmptyNodes( child );
+
+			if ( ( child instanceof THREE.Group || child.constructor === THREE.Object3D )
+                && child.children.length === 0 ) {
+
+				object.remove( child );
+
+			}
+
+		}
+
+	}
+
+	disposeMeshes( meshesToRemove ) {
+
+		meshesToRemove.forEach( ( mesh ) => {
+
+			if ( mesh.parent ) {
+
+				mesh.parent.remove( mesh );
+
+			}
+
+			if ( mesh.geometry ) mesh.geometry.dispose();
+			if ( mesh.material ) {
+
+				if ( Array.isArray( mesh.material ) ) {
+
+					mesh.material.forEach( ( m ) => m.dispose() );
+
+				} else {
+
+					mesh.material.dispose();
+
+				}
+
+			}
+
+		} );
+
+	}
+
+	logDebugInfo( stats ) {
+
+		console.group( 'Scene Optimization Results' );
+		console.log( `Original meshes: ${stats.originalMeshes}` );
+		console.log( `Batched into: ${stats.batchedMeshes} BatchedMesh` );
+		console.log( `Single meshes: ${stats.singleMeshes} Mesh` );
+		console.log( `Total draw calls: ${stats.drawCalls}` );
+		console.log( `Reduction Ratio: ${stats.reductionRatio}% fewer draw calls` );
+		console.groupEnd();
+
+	}
+
+	toBatchedMesh() {
+
+		const { batchGroups, singleGroups, uniqueGeometries } = this.analyzeModel();
+		const meshesToRemove = this.createBatchedMeshes( batchGroups );
+
+		this.disposeMeshes( meshesToRemove );
+		this.removeEmptyNodes( this.scene );
+
+		if ( this.debug ) {
+
+			const totalOriginalMeshes = meshesToRemove.size + singleGroups.size;
+			const totalFinalMeshes = batchGroups.size + singleGroups.size;
+
+			const stats = {
+				originalMeshes: totalOriginalMeshes,
+				batchedMeshes: batchGroups.size,
+				singleMeshes: singleGroups.size,
+				drawCalls: totalFinalMeshes,
+				uniqueGeometries: uniqueGeometries,
+				reductionRatio: ( ( 1 - totalFinalMeshes / totalOriginalMeshes ) * 100 ).toFixed( 1 ),
+			};
+
+			this.logDebugInfo( stats );
+
+		}
+
+		return this.scene;
+
+	}
+
+	// Placeholder for future implementation
+	toInstancingMesh() {
+
+		throw new Error( 'InstancedMesh optimization not implemented yet' );
+
+	}
+
+}
+
+export { SceneOptimizer };

+ 1 - 1
examples/jsm/utils/UVsDebug.js

@@ -6,7 +6,7 @@ import {
  * tool for "unwrapping" and debugging three.js geometries UV mapping
  *
  * Sample usage:
- *	document.body.appendChild( UVsDebug( new THREE.SphereGeometry( 10, 10, 10, 10 ) );
+ *	document.body.appendChild( UVsDebug( new THREE.SphereGeometry( 10, 10, 10, 10 ) ) );
  *
  */
 

+ 1 - 0
examples/misc_controls_arcball.html

@@ -59,6 +59,7 @@
 				populateGui: function () {
 
 					folderOptions.add( controls, 'enabled' ).name( 'Enable controls' );
+					folderOptions.add( controls, 'enableFocus' ).name( 'Enable focus' );
 					folderOptions.add( controls, 'enableGrid' ).name( 'Enable Grid' );
 					folderOptions.add( controls, 'enableRotate' ).name( 'Enable rotate' );
 					folderOptions.add( controls, 'enablePan' ).name( 'Enable pan' );

+ 3 - 2
examples/misc_controls_fly.html

@@ -31,7 +31,8 @@
 			{
 				"imports": {
 					"three": "../build/three.webgpu.js",
-					"three/tsl": "../build/three.webgpu.js",
+					"three/webgpu": "../build/three.webgpu.js",
+					"three/tsl": "../build/three.tsl.js",
 					"three/addons/": "./jsm/"
 				}
 			}
@@ -39,7 +40,7 @@
 
 		<script type="module">
 
-			import * as THREE from 'three';
+			import * as THREE from 'three/webgpu';
 			import { pass } from 'three/tsl';
 			import { film } from 'three/addons/tsl/display/FilmNode.js';
 

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.

粤ICP备19079148号