@nice2dev/ui-3d 1.3.14 → 1.3.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/collaborative/collaborativeScene.js +160 -206
  3. package/dist/cjs/core/editorAsk.js +51 -41
  4. package/dist/cjs/core/i18n.js +13 -14
  5. package/dist/cjs/core/threeCompat.js +29 -42
  6. package/dist/cjs/dance/DanceBridge.js +148 -177
  7. package/dist/cjs/dance/DanceScoreEngine.js +209 -221
  8. package/dist/cjs/dance/PoseDetector.js +302 -275
  9. package/dist/cjs/index.js +110 -113
  10. package/dist/cjs/material/MaterialEditor.module.css.js +242 -5
  11. package/dist/cjs/material/NiceMaterialEditor.js +1213 -757
  12. package/dist/cjs/material/materialEditorTypes.js +35 -49
  13. package/dist/cjs/material/materialEditorUtils.js +684 -747
  14. package/dist/cjs/material/materialNodeDefinitions.js +1411 -1459
  15. package/dist/cjs/model/ModelEditor.js +90 -40
  16. package/dist/cjs/model/ModelEditor.module.css.js +257 -5
  17. package/dist/cjs/model/ModelEditorLeftPanel.js +126 -47
  18. package/dist/cjs/model/ModelEditorMenuBar.js +359 -32
  19. package/dist/cjs/model/ModelEditorRightPanel.js +647 -131
  20. package/dist/cjs/model/ModelEditorSubComponents.js +277 -112
  21. package/dist/cjs/model/ModelEditorTimeline.js +232 -34
  22. package/dist/cjs/model/ModelEditorToolbar.js +170 -14
  23. package/dist/cjs/model/ModelEditorViewport.js +231 -39
  24. package/dist/cjs/model/ModelViewer.js +388 -63
  25. package/dist/cjs/model/ModelViewer.module.css.js +77 -5
  26. package/dist/cjs/model/NiceArmatureEditor.js +473 -274
  27. package/dist/cjs/model/NiceMorphTargetEditor.js +333 -227
  28. package/dist/cjs/model/NiceOctree.js +372 -320
  29. package/dist/cjs/model/NicePhysicsSimulation.js +528 -298
  30. package/dist/cjs/model/NiceProceduralGeometry.js +673 -300
  31. package/dist/cjs/model/NiceTerrainEditor.js +595 -385
  32. package/dist/cjs/model/NiceWeightPainter.js +384 -261
  33. package/dist/cjs/model/NiceXRPreview.js +385 -308
  34. package/dist/cjs/model/cadModeUtils.js +103 -106
  35. package/dist/cjs/model/editorShortcuts.js +171 -194
  36. package/dist/cjs/model/modelEditorTypes.js +100 -118
  37. package/dist/cjs/model/modelEditorUtils.js +1061 -1146
  38. package/dist/cjs/model/simsModeUtils.js +1023 -1053
  39. package/dist/cjs/model/useModelEditor.js +1977 -1933
  40. package/dist/cjs/model/useModelViewer.js +633 -665
  41. package/dist/cjs/nice2dev-ui-3d.css +1 -1
  42. package/dist/cjs/particle/NiceParticleEditor.js +1186 -571
  43. package/dist/cjs/particle/ParticleEditor.module.css.js +122 -5
  44. package/dist/cjs/particle/particleEditorTypes.js +62 -70
  45. package/dist/cjs/particle/particleEditorUtils.js +998 -1013
  46. package/dist/cjs/rendering/NiceCascadedShadows.js +381 -259
  47. package/dist/cjs/rendering/NiceRenderExport.js +424 -337
  48. package/dist/cjs/rendering/NiceSSAO.js +454 -337
  49. package/dist/cjs/rendering/NiceSSR.js +387 -261
  50. package/dist/cjs/rendering/NiceWebGPURenderer.js +359 -230
  51. package/dist/cjs/uv/NiceUVEditor.js +787 -550
  52. package/dist/cjs/uv/UVEditor.module.css.js +53 -5
  53. package/dist/cjs/uv/uvEditorTypes.js +59 -76
  54. package/dist/cjs/uv/uvEditorUtils.js +501 -575
  55. package/dist/esm/collaborative/collaborativeScene.js +163 -205
  56. package/dist/esm/core/editorAsk.js +53 -40
  57. package/dist/esm/core/i18n.js +15 -13
  58. package/dist/esm/core/threeCompat.js +18 -26
  59. package/dist/esm/dance/DanceBridge.js +151 -176
  60. package/dist/esm/dance/DanceScoreEngine.js +211 -220
  61. package/dist/esm/dance/PoseDetector.js +304 -274
  62. package/dist/esm/index.js +258 -36
  63. package/dist/esm/material/MaterialEditor.module.css.js +242 -3
  64. package/dist/esm/material/NiceMaterialEditor.js +1215 -756
  65. package/dist/esm/material/materialEditorTypes.js +45 -48
  66. package/dist/esm/material/materialEditorUtils.js +713 -746
  67. package/dist/esm/material/materialNodeDefinitions.js +1415 -1458
  68. package/dist/esm/model/ModelEditor.js +91 -39
  69. package/dist/esm/model/ModelEditor.module.css.js +257 -3
  70. package/dist/esm/model/ModelEditorLeftPanel.js +126 -45
  71. package/dist/esm/model/ModelEditorMenuBar.js +359 -30
  72. package/dist/esm/model/ModelEditorRightPanel.js +634 -114
  73. package/dist/esm/model/ModelEditorSubComponents.js +265 -94
  74. package/dist/esm/model/ModelEditorTimeline.js +232 -32
  75. package/dist/esm/model/ModelEditorToolbar.js +170 -12
  76. package/dist/esm/model/ModelEditorViewport.js +231 -37
  77. package/dist/esm/model/ModelViewer.js +389 -62
  78. package/dist/esm/model/ModelViewer.module.css.js +77 -3
  79. package/dist/esm/model/NiceArmatureEditor.js +462 -258
  80. package/dist/esm/model/NiceMorphTargetEditor.js +322 -211
  81. package/dist/esm/model/NiceOctree.js +361 -304
  82. package/dist/esm/model/NicePhysicsSimulation.js +517 -282
  83. package/dist/esm/model/NiceProceduralGeometry.js +667 -284
  84. package/dist/esm/model/NiceTerrainEditor.js +584 -369
  85. package/dist/esm/model/NiceWeightPainter.js +373 -245
  86. package/dist/esm/model/NiceXRPreview.js +374 -292
  87. package/dist/esm/model/cadModeUtils.js +95 -88
  88. package/dist/esm/model/editorShortcuts.js +172 -193
  89. package/dist/esm/model/modelEditorTypes.js +90 -100
  90. package/dist/esm/model/modelEditorUtils.js +1056 -1128
  91. package/dist/esm/model/simsModeUtils.js +1021 -1035
  92. package/dist/esm/model/useModelEditor.js +1946 -1920
  93. package/dist/esm/model/useModelViewer.js +619 -647
  94. package/dist/esm/nice2dev-ui-3d.css +1 -1
  95. package/dist/esm/particle/NiceParticleEditor.js +1188 -570
  96. package/dist/esm/particle/ParticleEditor.module.css.js +122 -3
  97. package/dist/esm/particle/particleEditorTypes.js +69 -69
  98. package/dist/esm/particle/particleEditorUtils.js +1027 -1012
  99. package/dist/esm/rendering/NiceCascadedShadows.js +370 -243
  100. package/dist/esm/rendering/NiceRenderExport.js +413 -321
  101. package/dist/esm/rendering/NiceSSAO.js +450 -328
  102. package/dist/esm/rendering/NiceSSR.js +383 -252
  103. package/dist/esm/rendering/NiceWebGPURenderer.js +326 -214
  104. package/dist/esm/uv/NiceUVEditor.js +788 -549
  105. package/dist/esm/uv/UVEditor.module.css.js +53 -3
  106. package/dist/esm/uv/uvEditorTypes.js +68 -75
  107. package/dist/esm/uv/uvEditorUtils.js +515 -557
  108. package/package.json +7 -12
@@ -1,285 +1,411 @@
1
- 'use strict';
2
-
3
- var jsxRuntime = require('react/jsx-runtime');
4
- var ui = require('@nice2dev/ui');
5
- var React = require('react');
6
- var THREE = require('three');
7
- var i18n = require('../core/i18n.js');
8
-
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const ui = require("@nice2dev/ui");
5
+ const React = require("react");
6
+ const THREE = require("three");
7
+ const i18n = require("../core/i18n.js");
9
8
  function _interopNamespaceDefault(e) {
10
- var n = Object.create(null);
9
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
11
10
  if (e) {
12
- Object.keys(e).forEach(function (k) {
13
- if (k !== 'default') {
14
- var d = Object.getOwnPropertyDescriptor(e, k);
11
+ for (const k in e) {
12
+ if (k !== "default") {
13
+ const d = Object.getOwnPropertyDescriptor(e, k);
15
14
  Object.defineProperty(n, k, d.get ? d : {
16
15
  enumerable: true,
17
- get: function () { return e[k]; }
16
+ get: () => e[k]
18
17
  });
19
18
  }
20
- });
19
+ }
21
20
  }
22
21
  n.default = e;
23
22
  return Object.freeze(n);
24
23
  }
24
+ const THREE__namespace = /* @__PURE__ */ _interopNamespaceDefault(THREE);
25
+ const SSR_VERTEX = `
26
+ varying vec2 vUv;
27
+ void main() {
28
+ vUv = uv;
29
+ gl_Position = vec4(position, 1.0);
30
+ }
31
+ `;
32
+ const SSR_FRAGMENT = `
33
+ uniform sampler2D tDiffuse;
34
+ uniform sampler2D tDepth;
35
+ uniform sampler2D tNormal;
36
+ uniform mat4 projMatrix;
37
+ uniform mat4 projInverseMatrix;
38
+ uniform mat4 viewMatrix;
39
+ uniform vec2 resolution;
40
+ uniform float cameraNear;
41
+ uniform float cameraFar;
42
+ uniform int maxSteps;
43
+ uniform float maxDistance;
44
+ uniform float thickness;
45
+ uniform float jitter;
46
+ uniform float intensity;
47
+ uniform float fresnelExponent;
25
48
 
26
- var THREE__namespace = /*#__PURE__*/_interopNamespaceDefault(THREE);
49
+ varying vec2 vUv;
27
50
 
28
- /* ── SSR Shader ── */
29
- const SSR_VERTEX = `
30
- varying vec2 vUv;
31
- void main() {
32
- vUv = uv;
33
- gl_Position = vec4(position, 1.0);
34
- }
35
- `;
36
- const SSR_FRAGMENT = `
37
- uniform sampler2D tDiffuse;
38
- uniform sampler2D tDepth;
39
- uniform sampler2D tNormal;
40
- uniform mat4 projMatrix;
41
- uniform mat4 projInverseMatrix;
42
- uniform mat4 viewMatrix;
43
- uniform vec2 resolution;
44
- uniform float cameraNear;
45
- uniform float cameraFar;
46
- uniform int maxSteps;
47
- uniform float maxDistance;
48
- uniform float thickness;
49
- uniform float jitter;
50
- uniform float intensity;
51
- uniform float fresnelExponent;
52
-
53
- varying vec2 vUv;
54
-
55
- float getDepth(vec2 uv) {
56
- float d = texture2D(tDepth, uv).r;
57
- return cameraNear * cameraFar / (cameraFar - d * (cameraFar - cameraNear));
58
- }
59
-
60
- vec3 getViewPosition(vec2 uv, float depth) {
61
- vec4 clipPos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
62
- vec4 viewPos = projInverseMatrix * clipPos;
63
- return viewPos.xyz / viewPos.w;
64
- }
65
-
66
- vec3 getViewNormal(vec2 uv) {
67
- return normalize(texture2D(tNormal, uv).xyz * 2.0 - 1.0);
68
- }
69
-
70
- float fresnel(vec3 viewDir, vec3 normal, float exponent) {
71
- return pow(1.0 - max(dot(-viewDir, normal), 0.0), exponent);
72
- }
73
-
74
- vec2 rayMarch(vec3 origin, vec3 direction) {
75
- vec3 pos = origin;
76
- float stepSize = maxDistance / float(maxSteps);
77
-
78
- for (int i = 0; i < 256; i++) {
79
- if (i >= maxSteps) break;
80
-
81
- pos += direction * stepSize;
82
-
83
- // Project to screen space
84
- vec4 projPos = projMatrix * vec4(pos, 1.0);
85
- projPos.xyz /= projPos.w;
86
- vec2 screenUv = projPos.xy * 0.5 + 0.5;
87
-
88
- // Out of screen
89
- if (screenUv.x < 0.0 || screenUv.x > 1.0 || screenUv.y < 0.0 || screenUv.y > 1.0) {
90
- return vec2(-1.0);
91
- }
92
-
93
- float sceneDepth = getDepth(screenUv);
94
- float rayDepth = -pos.z;
95
-
96
- if (rayDepth > sceneDepth && rayDepth - sceneDepth < thickness) {
97
- return screenUv;
98
- }
99
- }
100
-
101
- return vec2(-1.0);
102
- }
103
-
104
- void main() {
105
- vec4 baseColor = texture2D(tDiffuse, vUv);
106
- float depth = texture2D(tDepth, vUv).r;
107
-
108
- if (depth >= 1.0) {
109
- gl_FragColor = baseColor;
110
- return;
111
- }
112
-
113
- vec3 viewPos = getViewPosition(vUv, depth);
114
- vec3 viewNormal = getViewNormal(vUv);
115
- vec3 viewDir = normalize(viewPos);
116
-
117
- // Reflect view direction around normal
118
- vec3 reflectDir = reflect(viewDir, viewNormal);
119
-
120
- // Add jitter
121
- float j = fract(sin(dot(vUv, vec2(12.9898, 78.233))) * 43758.5453) * jitter;
122
- reflectDir += j * 0.01;
123
- reflectDir = normalize(reflectDir);
124
-
125
- // Ray march
126
- vec2 hitUv = rayMarch(viewPos + viewNormal * 0.01, reflectDir);
127
-
128
- vec3 reflection = vec3(0.0);
129
- if (hitUv.x >= 0.0) {
130
- reflection = texture2D(tDiffuse, hitUv).rgb;
131
- }
132
-
133
- // Fresnel attenuation
134
- float f = fresnel(viewDir, viewNormal, fresnelExponent);
135
-
136
- gl_FragColor = vec4(mix(baseColor.rgb, reflection, f * intensity), baseColor.a);
137
- }
51
+ float getDepth(vec2 uv) {
52
+ float d = texture2D(tDepth, uv).r;
53
+ return cameraNear * cameraFar / (cameraFar - d * (cameraFar - cameraNear));
54
+ }
55
+
56
+ vec3 getViewPosition(vec2 uv, float depth) {
57
+ vec4 clipPos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
58
+ vec4 viewPos = projInverseMatrix * clipPos;
59
+ return viewPos.xyz / viewPos.w;
60
+ }
61
+
62
+ vec3 getViewNormal(vec2 uv) {
63
+ return normalize(texture2D(tNormal, uv).xyz * 2.0 - 1.0);
64
+ }
65
+
66
+ float fresnel(vec3 viewDir, vec3 normal, float exponent) {
67
+ return pow(1.0 - max(dot(-viewDir, normal), 0.0), exponent);
68
+ }
69
+
70
+ vec2 rayMarch(vec3 origin, vec3 direction) {
71
+ vec3 pos = origin;
72
+ float stepSize = maxDistance / float(maxSteps);
73
+
74
+ for (int i = 0; i < 256; i++) {
75
+ if (i >= maxSteps) break;
76
+
77
+ pos += direction * stepSize;
78
+
79
+ // Project to screen space
80
+ vec4 projPos = projMatrix * vec4(pos, 1.0);
81
+ projPos.xyz /= projPos.w;
82
+ vec2 screenUv = projPos.xy * 0.5 + 0.5;
83
+
84
+ // Out of screen
85
+ if (screenUv.x < 0.0 || screenUv.x > 1.0 || screenUv.y < 0.0 || screenUv.y > 1.0) {
86
+ return vec2(-1.0);
87
+ }
88
+
89
+ float sceneDepth = getDepth(screenUv);
90
+ float rayDepth = -pos.z;
91
+
92
+ if (rayDepth > sceneDepth && rayDepth - sceneDepth < thickness) {
93
+ return screenUv;
94
+ }
95
+ }
96
+
97
+ return vec2(-1.0);
98
+ }
99
+
100
+ void main() {
101
+ vec4 baseColor = texture2D(tDiffuse, vUv);
102
+ float depth = texture2D(tDepth, vUv).r;
103
+
104
+ if (depth >= 1.0) {
105
+ gl_FragColor = baseColor;
106
+ return;
107
+ }
108
+
109
+ vec3 viewPos = getViewPosition(vUv, depth);
110
+ vec3 viewNormal = getViewNormal(vUv);
111
+ vec3 viewDir = normalize(viewPos);
112
+
113
+ // Reflect view direction around normal
114
+ vec3 reflectDir = reflect(viewDir, viewNormal);
115
+
116
+ // Add jitter
117
+ float j = fract(sin(dot(vUv, vec2(12.9898, 78.233))) * 43758.5453) * jitter;
118
+ reflectDir += j * 0.01;
119
+ reflectDir = normalize(reflectDir);
120
+
121
+ // Ray march
122
+ vec2 hitUv = rayMarch(viewPos + viewNormal * 0.01, reflectDir);
123
+
124
+ vec3 reflection = vec3(0.0);
125
+ if (hitUv.x >= 0.0) {
126
+ reflection = texture2D(tDiffuse, hitUv).rgb;
127
+ }
128
+
129
+ // Fresnel attenuation
130
+ float f = fresnel(viewDir, viewNormal, fresnelExponent);
131
+
132
+ gl_FragColor = vec4(mix(baseColor.rgb, reflection, f * intensity), baseColor.a);
133
+ }
138
134
  `;
139
- /* ── Hook ── */
140
135
  const DEFAULT_SSR = {
141
- enabled: true,
142
- maxSteps: 64,
143
- maxDistance: 50,
144
- thickness: 0.5,
145
- resolution: 0.5,
146
- jitter: 0.3,
147
- intensity: 0.6,
148
- roughnessFade: 0.8,
149
- fresnelExponent: 3.0,
136
+ enabled: true,
137
+ maxSteps: 64,
138
+ maxDistance: 50,
139
+ thickness: 0.5,
140
+ resolution: 0.5,
141
+ jitter: 0.3,
142
+ intensity: 0.6,
143
+ roughnessFade: 0.8,
144
+ fresnelExponent: 3
150
145
  };
151
146
  function useSSR(renderer, scene, camera, configOverride) {
152
- const [config, setConfigState] = React.useState({ ...DEFAULT_SSR, ...configOverride });
153
- const [renderTarget, setRenderTarget] = React.useState(null);
154
- const depthTarget = React.useRef(null);
155
- const normalTarget = React.useRef(null);
156
- const ssrMaterial = React.useRef(null);
157
- const fullScreenQuad = React.useRef(null);
158
- const orthoScene = React.useRef(new THREE__namespace.Scene());
159
- const orthoCamera = React.useRef(new THREE__namespace.OrthographicCamera(-1, 1, 1, -1, 0, 1));
160
- const setConfig = React.useCallback((partial) => {
161
- setConfigState((prev) => ({ ...prev, ...partial }));
162
- }, []);
163
- // Setup render targets and shader
164
- React.useEffect(() => {
165
- if (!renderer || !camera) {
166
- return;
147
+ const [config, setConfigState] = React.useState({ ...DEFAULT_SSR, ...configOverride });
148
+ const [renderTarget, setRenderTarget] = React.useState(null);
149
+ const depthTarget = React.useRef(null);
150
+ const normalTarget = React.useRef(null);
151
+ const ssrMaterial = React.useRef(null);
152
+ const fullScreenQuad = React.useRef(null);
153
+ const orthoScene = React.useRef(new THREE__namespace.Scene());
154
+ const orthoCamera = React.useRef(new THREE__namespace.OrthographicCamera(-1, 1, 1, -1, 0, 1));
155
+ const setConfig = React.useCallback((partial) => {
156
+ setConfigState((prev) => ({ ...prev, ...partial }));
157
+ }, []);
158
+ React.useEffect(() => {
159
+ if (!renderer || !camera) {
160
+ return;
161
+ }
162
+ const width = Math.floor(renderer.domElement.width * config.resolution);
163
+ const height = Math.floor(renderer.domElement.height * config.resolution);
164
+ const sceneRT = new THREE__namespace.WebGLRenderTarget(width, height, {
165
+ minFilter: THREE__namespace.LinearFilter,
166
+ magFilter: THREE__namespace.LinearFilter,
167
+ format: THREE__namespace.RGBAFormat,
168
+ type: THREE__namespace.HalfFloatType
169
+ });
170
+ setRenderTarget(sceneRT);
171
+ const dTarget = new THREE__namespace.WebGLRenderTarget(width, height, {
172
+ minFilter: THREE__namespace.NearestFilter,
173
+ magFilter: THREE__namespace.NearestFilter,
174
+ format: THREE__namespace.RGBAFormat,
175
+ type: THREE__namespace.FloatType
176
+ });
177
+ dTarget.depthTexture = new THREE__namespace.DepthTexture(width, height);
178
+ dTarget.depthTexture.type = THREE__namespace.UnsignedIntType;
179
+ depthTarget.current = dTarget;
180
+ const nTarget = new THREE__namespace.WebGLRenderTarget(width, height, {
181
+ minFilter: THREE__namespace.NearestFilter,
182
+ magFilter: THREE__namespace.NearestFilter,
183
+ format: THREE__namespace.RGBAFormat
184
+ });
185
+ normalTarget.current = nTarget;
186
+ const material = new THREE__namespace.ShaderMaterial({
187
+ vertexShader: SSR_VERTEX,
188
+ fragmentShader: SSR_FRAGMENT,
189
+ uniforms: {
190
+ tDiffuse: { value: sceneRT.texture },
191
+ tDepth: { value: dTarget.depthTexture },
192
+ tNormal: { value: nTarget.texture },
193
+ projMatrix: { value: camera.projectionMatrix },
194
+ projInverseMatrix: { value: camera.projectionMatrixInverse },
195
+ viewMatrix: { value: camera.matrixWorldInverse },
196
+ resolution: { value: new THREE__namespace.Vector2(width, height) },
197
+ cameraNear: { value: camera.near },
198
+ cameraFar: { value: camera.far },
199
+ maxSteps: { value: config.maxSteps },
200
+ maxDistance: { value: config.maxDistance },
201
+ thickness: { value: config.thickness },
202
+ jitter: { value: config.jitter },
203
+ intensity: { value: config.intensity },
204
+ fresnelExponent: { value: config.fresnelExponent }
205
+ }
206
+ });
207
+ ssrMaterial.current = material;
208
+ const quad = new THREE__namespace.Mesh(new THREE__namespace.PlaneGeometry(2, 2), material);
209
+ quad.frustumCulled = false;
210
+ const ortho = orthoScene.current;
211
+ ortho.add(quad);
212
+ fullScreenQuad.current = quad;
213
+ return () => {
214
+ sceneRT.dispose();
215
+ dTarget.dispose();
216
+ nTarget.dispose();
217
+ material.dispose();
218
+ ortho.remove(quad);
219
+ };
220
+ }, [renderer, camera, config.resolution]);
221
+ React.useEffect(() => {
222
+ if (!ssrMaterial.current) {
223
+ return;
224
+ }
225
+ const u = ssrMaterial.current.uniforms;
226
+ u.maxSteps.value = config.maxSteps;
227
+ u.maxDistance.value = config.maxDistance;
228
+ u.thickness.value = config.thickness;
229
+ u.jitter.value = config.jitter;
230
+ u.intensity.value = config.intensity;
231
+ u.fresnelExponent.value = config.fresnelExponent;
232
+ }, [config]);
233
+ const update = React.useCallback(() => {
234
+ if (!renderer || !scene || !camera || !config.enabled) {
235
+ return;
236
+ }
237
+ if (!renderTarget || !depthTarget.current) {
238
+ return;
239
+ }
240
+ renderer.setRenderTarget(depthTarget.current);
241
+ renderer.render(scene, camera);
242
+ renderer.setRenderTarget(renderTarget);
243
+ renderer.render(scene, camera);
244
+ if (ssrMaterial.current) {
245
+ ssrMaterial.current.uniforms.projMatrix.value.copy(camera.projectionMatrix);
246
+ ssrMaterial.current.uniforms.projInverseMatrix.value.copy(camera.projectionMatrixInverse);
247
+ ssrMaterial.current.uniforms.viewMatrix.value.copy(camera.matrixWorldInverse);
248
+ }
249
+ renderer.setRenderTarget(null);
250
+ renderer.render(orthoScene.current, orthoCamera.current);
251
+ }, [renderer, scene, camera, config.enabled, renderTarget]);
252
+ const dispose = React.useCallback(() => {
253
+ renderTarget?.dispose();
254
+ depthTarget.current?.dispose();
255
+ normalTarget.current?.dispose();
256
+ ssrMaterial.current?.dispose();
257
+ }, [renderTarget]);
258
+ return { config, setConfig, renderTarget, update, dispose };
259
+ }
260
+ const NiceSSR = ({
261
+ renderer,
262
+ scene,
263
+ camera,
264
+ config: configProp,
265
+ className = ""
266
+ }) => {
267
+ const { t } = i18n.useNiceTranslation();
268
+ const { config, setConfig } = useSSR(renderer, scene, camera, configProp);
269
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `nice-ssr ${className}`, style: { display: "grid", gap: 8, fontSize: 13 }, children: [
270
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
271
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
272
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "copy", size: 14 }),
273
+ " ",
274
+ t("ssr.screenSpaceReflections", "Screen-Space Reflections")
275
+ ] }),
276
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { style: { display: "flex", alignItems: "center", gap: 4, fontSize: 11 }, children: [
277
+ /* @__PURE__ */ jsxRuntime.jsx(
278
+ "input",
279
+ {
280
+ type: "checkbox",
281
+ checked: config.enabled,
282
+ onChange: (e) => setConfig({ enabled: e.target.checked })
283
+ }
284
+ ),
285
+ t("ssr.enabled", "Enabled")
286
+ ] })
287
+ ] }),
288
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
289
+ t("ssr.maxSteps", "Max Steps: {maxSteps}").replace("{maxSteps}", String(config.maxSteps)),
290
+ /* @__PURE__ */ jsxRuntime.jsx(
291
+ "input",
292
+ {
293
+ type: "range",
294
+ min: 16,
295
+ max: 256,
296
+ step: 16,
297
+ value: config.maxSteps,
298
+ onChange: (e) => setConfig({ maxSteps: parseInt(e.target.value, 10) }),
299
+ style: { width: "100%" }
167
300
  }
168
- const width = Math.floor(renderer.domElement.width * config.resolution);
169
- const height = Math.floor(renderer.domElement.height * config.resolution);
170
- // Scene render target
171
- const sceneRT = new THREE__namespace.WebGLRenderTarget(width, height, {
172
- minFilter: THREE__namespace.LinearFilter,
173
- magFilter: THREE__namespace.LinearFilter,
174
- format: THREE__namespace.RGBAFormat,
175
- type: THREE__namespace.HalfFloatType,
176
- });
177
- setRenderTarget(sceneRT);
178
- // Depth render target
179
- const dTarget = new THREE__namespace.WebGLRenderTarget(width, height, {
180
- minFilter: THREE__namespace.NearestFilter,
181
- magFilter: THREE__namespace.NearestFilter,
182
- format: THREE__namespace.RGBAFormat,
183
- type: THREE__namespace.FloatType,
184
- });
185
- dTarget.depthTexture = new THREE__namespace.DepthTexture(width, height);
186
- dTarget.depthTexture.type = THREE__namespace.UnsignedIntType;
187
- depthTarget.current = dTarget;
188
- // Normal render target
189
- const nTarget = new THREE__namespace.WebGLRenderTarget(width, height, {
190
- minFilter: THREE__namespace.NearestFilter,
191
- magFilter: THREE__namespace.NearestFilter,
192
- format: THREE__namespace.RGBAFormat,
193
- });
194
- normalTarget.current = nTarget;
195
- // SSR shader material
196
- const material = new THREE__namespace.ShaderMaterial({
197
- vertexShader: SSR_VERTEX,
198
- fragmentShader: SSR_FRAGMENT,
199
- uniforms: {
200
- tDiffuse: { value: sceneRT.texture },
201
- tDepth: { value: dTarget.depthTexture },
202
- tNormal: { value: nTarget.texture },
203
- projMatrix: { value: camera.projectionMatrix },
204
- projInverseMatrix: { value: camera.projectionMatrixInverse },
205
- viewMatrix: { value: camera.matrixWorldInverse },
206
- resolution: { value: new THREE__namespace.Vector2(width, height) },
207
- cameraNear: { value: camera.near },
208
- cameraFar: { value: camera.far },
209
- maxSteps: { value: config.maxSteps },
210
- maxDistance: { value: config.maxDistance },
211
- thickness: { value: config.thickness },
212
- jitter: { value: config.jitter },
213
- intensity: { value: config.intensity },
214
- fresnelExponent: { value: config.fresnelExponent },
215
- },
216
- });
217
- ssrMaterial.current = material;
218
- // Full-screen quad
219
- const quad = new THREE__namespace.Mesh(new THREE__namespace.PlaneGeometry(2, 2), material);
220
- quad.frustumCulled = false;
221
- const ortho = orthoScene.current;
222
- ortho.add(quad);
223
- fullScreenQuad.current = quad;
224
- return () => {
225
- sceneRT.dispose();
226
- dTarget.dispose();
227
- nTarget.dispose();
228
- material.dispose();
229
- ortho.remove(quad);
230
- };
231
- // eslint-disable-next-line react-hooks/exhaustive-deps -- the uniforms' first values; the next effect updates them without rebuilding the render targets
232
- }, [renderer, camera, config.resolution]);
233
- // Update uniforms when config changes
234
- React.useEffect(() => {
235
- if (!ssrMaterial.current) {
236
- return;
301
+ )
302
+ ] }),
303
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
304
+ t("ssr.maxDistance", "Max Distance: {maxDistance}").replace(
305
+ "{maxDistance}",
306
+ String(config.maxDistance)
307
+ ),
308
+ /* @__PURE__ */ jsxRuntime.jsx(
309
+ "input",
310
+ {
311
+ type: "range",
312
+ min: 5,
313
+ max: 200,
314
+ step: 5,
315
+ value: config.maxDistance,
316
+ onChange: (e) => setConfig({ maxDistance: parseInt(e.target.value, 10) }),
317
+ style: { width: "100%" }
237
318
  }
238
- const u = ssrMaterial.current.uniforms;
239
- u.maxSteps.value = config.maxSteps;
240
- u.maxDistance.value = config.maxDistance;
241
- u.thickness.value = config.thickness;
242
- u.jitter.value = config.jitter;
243
- u.intensity.value = config.intensity;
244
- u.fresnelExponent.value = config.fresnelExponent;
245
- }, [config]);
246
- const update = React.useCallback(() => {
247
- if (!renderer || !scene || !camera || !config.enabled) {
248
- return;
319
+ )
320
+ ] }),
321
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
322
+ t("ssr.intensity", "Intensity: {intensity}").replace(
323
+ "{intensity}",
324
+ String(config.intensity.toFixed(2))
325
+ ),
326
+ /* @__PURE__ */ jsxRuntime.jsx(
327
+ "input",
328
+ {
329
+ type: "range",
330
+ min: 0,
331
+ max: 1,
332
+ step: 0.05,
333
+ value: config.intensity,
334
+ onChange: (e) => setConfig({ intensity: parseFloat(e.target.value) }),
335
+ style: { width: "100%" }
249
336
  }
250
- if (!renderTarget || !depthTarget.current) {
251
- return;
337
+ )
338
+ ] }),
339
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
340
+ t("ssr.thickness", "Thickness: {thickness}").replace(
341
+ "{thickness}",
342
+ String(config.thickness.toFixed(2))
343
+ ),
344
+ /* @__PURE__ */ jsxRuntime.jsx(
345
+ "input",
346
+ {
347
+ type: "range",
348
+ min: 0.05,
349
+ max: 2,
350
+ step: 0.05,
351
+ value: config.thickness,
352
+ onChange: (e) => setConfig({ thickness: parseFloat(e.target.value) }),
353
+ style: { width: "100%" }
252
354
  }
253
- // Render scene to render target (color + depth)
254
- renderer.setRenderTarget(depthTarget.current);
255
- renderer.render(scene, camera);
256
- renderer.setRenderTarget(renderTarget);
257
- renderer.render(scene, camera);
258
- // Update camera matrices in uniforms
259
- if (ssrMaterial.current) {
260
- ssrMaterial.current.uniforms.projMatrix.value.copy(camera.projectionMatrix);
261
- ssrMaterial.current.uniforms.projInverseMatrix.value.copy(camera.projectionMatrixInverse);
262
- ssrMaterial.current.uniforms.viewMatrix.value.copy(camera.matrixWorldInverse);
355
+ )
356
+ ] }),
357
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
358
+ t("ssr.jitter", "Jitter: {jitter}").replace("{jitter}", String(config.jitter.toFixed(2))),
359
+ /* @__PURE__ */ jsxRuntime.jsx(
360
+ "input",
361
+ {
362
+ type: "range",
363
+ min: 0,
364
+ max: 1,
365
+ step: 0.05,
366
+ value: config.jitter,
367
+ onChange: (e) => setConfig({ jitter: parseFloat(e.target.value) }),
368
+ style: { width: "100%" }
263
369
  }
264
- // Render SSR pass to screen
265
- renderer.setRenderTarget(null);
266
- renderer.render(orthoScene.current, orthoCamera.current);
267
- }, [renderer, scene, camera, config.enabled, renderTarget]);
268
- const dispose = React.useCallback(() => {
269
- var _a, _b, _c;
270
- renderTarget === null || renderTarget === void 0 ? void 0 : renderTarget.dispose();
271
- (_a = depthTarget.current) === null || _a === void 0 ? void 0 : _a.dispose();
272
- (_b = normalTarget.current) === null || _b === void 0 ? void 0 : _b.dispose();
273
- (_c = ssrMaterial.current) === null || _c === void 0 ? void 0 : _c.dispose();
274
- }, [renderTarget]);
275
- return { config, setConfig, renderTarget, update, dispose };
276
- }
277
- /* ── Component ── */
278
- const NiceSSR = ({ renderer, scene, camera, config: configProp, className = '', }) => {
279
- const { t } = i18n.useNiceTranslation();
280
- const { config, setConfig } = useSSR(renderer, scene, camera, configProp);
281
- return (jsxRuntime.jsxs("div", { className: `nice-ssr ${className}`, style: { display: 'grid', gap: 8, fontSize: 13 }, children: [jsxRuntime.jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' }, children: [jsxRuntime.jsxs("strong", { children: [jsxRuntime.jsx(ui.NiceIcon, { name: "copy", size: 14 }), ' ', t('ssr.screenSpaceReflections', 'Screen-Space Reflections')] }), jsxRuntime.jsxs("label", { style: { display: 'flex', alignItems: 'center', gap: 4, fontSize: 11 }, children: [jsxRuntime.jsx("input", { type: "checkbox", checked: config.enabled, onChange: (e) => setConfig({ enabled: e.target.checked }) }), t('ssr.enabled', 'Enabled')] })] }), jsxRuntime.jsxs("label", { children: [t('ssr.maxSteps', 'Max Steps: {maxSteps}').replace('{maxSteps}', String(config.maxSteps)), jsxRuntime.jsx("input", { type: "range", min: 16, max: 256, step: 16, value: config.maxSteps, onChange: (e) => setConfig({ maxSteps: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('ssr.maxDistance', 'Max Distance: {maxDistance}').replace('{maxDistance}', String(config.maxDistance)), jsxRuntime.jsx("input", { type: "range", min: 5, max: 200, step: 5, value: config.maxDistance, onChange: (e) => setConfig({ maxDistance: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('ssr.intensity', 'Intensity: {intensity}').replace('{intensity}', String(config.intensity.toFixed(2))), jsxRuntime.jsx("input", { type: "range", min: 0, max: 1, step: 0.05, value: config.intensity, onChange: (e) => setConfig({ intensity: parseFloat(e.target.value) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('ssr.thickness', 'Thickness: {thickness}').replace('{thickness}', String(config.thickness.toFixed(2))), jsxRuntime.jsx("input", { type: "range", min: 0.05, max: 2, step: 0.05, value: config.thickness, onChange: (e) => setConfig({ thickness: parseFloat(e.target.value) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('ssr.jitter', 'Jitter: {jitter}').replace('{jitter}', String(config.jitter.toFixed(2))), jsxRuntime.jsx("input", { type: "range", min: 0, max: 1, step: 0.05, value: config.jitter, onChange: (e) => setConfig({ jitter: parseFloat(e.target.value) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('ssr.resolutionScale', 'Resolution Scale: {resolution}').replace('{resolution}', String(config.resolution.toFixed(2))), jsxRuntime.jsx("input", { type: "range", min: 0.25, max: 1, step: 0.25, value: config.resolution, onChange: (e) => setConfig({ resolution: parseFloat(e.target.value) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('ssr.fresnel', 'Fresnel: {fresnelExponent}').replace('{fresnelExponent}', String(config.fresnelExponent.toFixed(1))), jsxRuntime.jsx("input", { type: "range", min: 1, max: 8, step: 0.5, value: config.fresnelExponent, onChange: (e) => setConfig({ fresnelExponent: parseFloat(e.target.value) }), style: { width: '100%' } })] })] }));
370
+ )
371
+ ] }),
372
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
373
+ t("ssr.resolutionScale", "Resolution Scale: {resolution}").replace(
374
+ "{resolution}",
375
+ String(config.resolution.toFixed(2))
376
+ ),
377
+ /* @__PURE__ */ jsxRuntime.jsx(
378
+ "input",
379
+ {
380
+ type: "range",
381
+ min: 0.25,
382
+ max: 1,
383
+ step: 0.25,
384
+ value: config.resolution,
385
+ onChange: (e) => setConfig({ resolution: parseFloat(e.target.value) }),
386
+ style: { width: "100%" }
387
+ }
388
+ )
389
+ ] }),
390
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
391
+ t("ssr.fresnel", "Fresnel: {fresnelExponent}").replace(
392
+ "{fresnelExponent}",
393
+ String(config.fresnelExponent.toFixed(1))
394
+ ),
395
+ /* @__PURE__ */ jsxRuntime.jsx(
396
+ "input",
397
+ {
398
+ type: "range",
399
+ min: 1,
400
+ max: 8,
401
+ step: 0.5,
402
+ value: config.fresnelExponent,
403
+ onChange: (e) => setConfig({ fresnelExponent: parseFloat(e.target.value) }),
404
+ style: { width: "100%" }
405
+ }
406
+ )
407
+ ] })
408
+ ] });
282
409
  };
283
-
284
410
  exports.NiceSSR = NiceSSR;
285
411
  exports.useSSR = useSSR;