@nice2dev/ui-3d 1.3.15 → 1.3.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/cjs/collaborative/collaborativeScene.js +160 -206
- package/dist/cjs/core/editorAsk.js +51 -41
- package/dist/cjs/core/i18n.js +13 -14
- package/dist/cjs/core/threeCompat.js +29 -42
- package/dist/cjs/dance/DanceBridge.js +148 -177
- package/dist/cjs/dance/DanceScoreEngine.js +209 -221
- package/dist/cjs/dance/PoseDetector.js +302 -275
- package/dist/cjs/index.js +110 -113
- package/dist/cjs/material/MaterialEditor.module.css.js +242 -5
- package/dist/cjs/material/NiceMaterialEditor.js +1213 -757
- package/dist/cjs/material/materialEditorTypes.js +35 -49
- package/dist/cjs/material/materialEditorUtils.js +684 -747
- package/dist/cjs/material/materialNodeDefinitions.js +1411 -1459
- package/dist/cjs/model/ModelEditor.js +90 -40
- package/dist/cjs/model/ModelEditor.module.css.js +257 -5
- package/dist/cjs/model/ModelEditorLeftPanel.js +126 -47
- package/dist/cjs/model/ModelEditorMenuBar.js +359 -32
- package/dist/cjs/model/ModelEditorRightPanel.js +647 -131
- package/dist/cjs/model/ModelEditorSubComponents.js +277 -112
- package/dist/cjs/model/ModelEditorTimeline.js +232 -34
- package/dist/cjs/model/ModelEditorToolbar.js +170 -14
- package/dist/cjs/model/ModelEditorViewport.js +231 -39
- package/dist/cjs/model/ModelViewer.js +388 -63
- package/dist/cjs/model/ModelViewer.module.css.js +77 -5
- package/dist/cjs/model/NiceArmatureEditor.js +473 -274
- package/dist/cjs/model/NiceMorphTargetEditor.js +333 -227
- package/dist/cjs/model/NiceOctree.js +372 -320
- package/dist/cjs/model/NicePhysicsSimulation.js +528 -298
- package/dist/cjs/model/NiceProceduralGeometry.js +673 -300
- package/dist/cjs/model/NiceTerrainEditor.js +595 -385
- package/dist/cjs/model/NiceWeightPainter.js +384 -261
- package/dist/cjs/model/NiceXRPreview.js +385 -308
- package/dist/cjs/model/cadModeUtils.js +103 -106
- package/dist/cjs/model/editorShortcuts.js +171 -194
- package/dist/cjs/model/modelEditorTypes.js +100 -118
- package/dist/cjs/model/modelEditorUtils.js +1061 -1146
- package/dist/cjs/model/simsModeUtils.js +1023 -1053
- package/dist/cjs/model/useModelEditor.js +1977 -1933
- package/dist/cjs/model/useModelViewer.js +633 -665
- package/dist/cjs/nice2dev-ui-3d.css +1 -1
- package/dist/cjs/particle/NiceParticleEditor.js +1186 -571
- package/dist/cjs/particle/ParticleEditor.module.css.js +122 -5
- package/dist/cjs/particle/particleEditorTypes.js +62 -70
- package/dist/cjs/particle/particleEditorUtils.js +998 -1013
- package/dist/cjs/rendering/NiceCascadedShadows.js +381 -259
- package/dist/cjs/rendering/NiceRenderExport.js +424 -337
- package/dist/cjs/rendering/NiceSSAO.js +454 -337
- package/dist/cjs/rendering/NiceSSR.js +387 -261
- package/dist/cjs/rendering/NiceWebGPURenderer.js +359 -230
- package/dist/cjs/uv/NiceUVEditor.js +787 -550
- package/dist/cjs/uv/UVEditor.module.css.js +53 -5
- package/dist/cjs/uv/uvEditorTypes.js +59 -76
- package/dist/cjs/uv/uvEditorUtils.js +501 -575
- package/dist/esm/collaborative/collaborativeScene.js +163 -205
- package/dist/esm/core/editorAsk.js +53 -40
- package/dist/esm/core/i18n.js +15 -13
- package/dist/esm/core/threeCompat.js +18 -26
- package/dist/esm/dance/DanceBridge.js +151 -176
- package/dist/esm/dance/DanceScoreEngine.js +211 -220
- package/dist/esm/dance/PoseDetector.js +304 -274
- package/dist/esm/index.js +258 -36
- package/dist/esm/material/MaterialEditor.module.css.js +242 -3
- package/dist/esm/material/NiceMaterialEditor.js +1215 -756
- package/dist/esm/material/materialEditorTypes.js +45 -48
- package/dist/esm/material/materialEditorUtils.js +713 -746
- package/dist/esm/material/materialNodeDefinitions.js +1415 -1458
- package/dist/esm/model/ModelEditor.js +91 -39
- package/dist/esm/model/ModelEditor.module.css.js +257 -3
- package/dist/esm/model/ModelEditorLeftPanel.js +126 -45
- package/dist/esm/model/ModelEditorMenuBar.js +359 -30
- package/dist/esm/model/ModelEditorRightPanel.js +634 -114
- package/dist/esm/model/ModelEditorSubComponents.js +265 -94
- package/dist/esm/model/ModelEditorTimeline.js +232 -32
- package/dist/esm/model/ModelEditorToolbar.js +170 -12
- package/dist/esm/model/ModelEditorViewport.js +231 -37
- package/dist/esm/model/ModelViewer.js +389 -62
- package/dist/esm/model/ModelViewer.module.css.js +77 -3
- package/dist/esm/model/NiceArmatureEditor.js +462 -258
- package/dist/esm/model/NiceMorphTargetEditor.js +322 -211
- package/dist/esm/model/NiceOctree.js +361 -304
- package/dist/esm/model/NicePhysicsSimulation.js +517 -282
- package/dist/esm/model/NiceProceduralGeometry.js +667 -284
- package/dist/esm/model/NiceTerrainEditor.js +584 -369
- package/dist/esm/model/NiceWeightPainter.js +373 -245
- package/dist/esm/model/NiceXRPreview.js +374 -292
- package/dist/esm/model/cadModeUtils.js +95 -88
- package/dist/esm/model/editorShortcuts.js +172 -193
- package/dist/esm/model/modelEditorTypes.js +90 -100
- package/dist/esm/model/modelEditorUtils.js +1056 -1128
- package/dist/esm/model/simsModeUtils.js +1021 -1035
- package/dist/esm/model/useModelEditor.js +1946 -1920
- package/dist/esm/model/useModelViewer.js +619 -647
- package/dist/esm/nice2dev-ui-3d.css +1 -1
- package/dist/esm/particle/NiceParticleEditor.js +1188 -570
- package/dist/esm/particle/ParticleEditor.module.css.js +122 -3
- package/dist/esm/particle/particleEditorTypes.js +69 -69
- package/dist/esm/particle/particleEditorUtils.js +1027 -1012
- package/dist/esm/rendering/NiceCascadedShadows.js +370 -243
- package/dist/esm/rendering/NiceRenderExport.js +413 -321
- package/dist/esm/rendering/NiceSSAO.js +450 -328
- package/dist/esm/rendering/NiceSSR.js +383 -252
- package/dist/esm/rendering/NiceWebGPURenderer.js +326 -214
- package/dist/esm/uv/NiceUVEditor.js +788 -549
- package/dist/esm/uv/UVEditor.module.css.js +53 -3
- package/dist/esm/uv/uvEditorTypes.js +68 -75
- package/dist/esm/uv/uvEditorUtils.js +515 -557
- package/package.json +7 -12
|
@@ -1,368 +1,485 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
9
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
11
10
|
if (e) {
|
|
12
|
-
|
|
13
|
-
if (k !==
|
|
14
|
-
|
|
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:
|
|
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 SSAO_VERTEX = `
|
|
26
|
+
varying vec2 vUv;
|
|
27
|
+
void main() {
|
|
28
|
+
vUv = uv;
|
|
29
|
+
gl_Position = vec4(position, 1.0);
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
const SSAO_FRAGMENT = `
|
|
33
|
+
uniform sampler2D tDepth;
|
|
34
|
+
uniform sampler2D tNoise;
|
|
35
|
+
uniform vec3 kernel[128];
|
|
36
|
+
uniform int kernelSize;
|
|
37
|
+
uniform vec2 resolution;
|
|
38
|
+
uniform mat4 projMatrix;
|
|
39
|
+
uniform mat4 projInverseMatrix;
|
|
40
|
+
uniform float cameraNear;
|
|
41
|
+
uniform float cameraFar;
|
|
42
|
+
uniform float radius;
|
|
43
|
+
uniform float bias;
|
|
44
|
+
uniform float intensity;
|
|
45
|
+
uniform float minDistance;
|
|
46
|
+
uniform float maxDistance;
|
|
25
47
|
|
|
26
|
-
|
|
48
|
+
varying vec2 vUv;
|
|
27
49
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
vec3
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (i >= kernelSize) break;
|
|
92
|
-
|
|
93
|
-
// Transform sample to view space
|
|
94
|
-
vec3 samplePos = TBN * kernel[i];
|
|
95
|
-
samplePos = viewPos + samplePos * radius;
|
|
96
|
-
|
|
97
|
-
// Project sample to screen
|
|
98
|
-
vec4 offset = projMatrix * vec4(samplePos, 1.0);
|
|
99
|
-
offset.xyz /= offset.w;
|
|
100
|
-
vec2 sampleUv = offset.xy * 0.5 + 0.5;
|
|
101
|
-
|
|
102
|
-
// Out of screen
|
|
103
|
-
if (sampleUv.x < 0.0 || sampleUv.x > 1.0 || sampleUv.y < 0.0 || sampleUv.y > 1.0) continue;
|
|
104
|
-
|
|
105
|
-
float sampleDepth = linearDepth(texture2D(tDepth, sampleUv).r);
|
|
106
|
-
float rangeCheck = smoothstep(0.0, 1.0, radius / abs(-viewPos.z - sampleDepth));
|
|
107
|
-
|
|
108
|
-
float dist = abs(-viewPos.z - sampleDepth);
|
|
109
|
-
if (dist >= minDistance && dist <= maxDistance) {
|
|
110
|
-
occlusion += (sampleDepth <= -samplePos.z - bias ? 1.0 : 0.0) * rangeCheck;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
occlusion = 1.0 - (occlusion / float(kernelSize)) * intensity;
|
|
115
|
-
gl_FragColor = vec4(vec3(occlusion), 1.0);
|
|
116
|
-
}
|
|
50
|
+
float linearDepth(float d) {
|
|
51
|
+
return cameraNear * cameraFar / (cameraFar - d * (cameraFar - cameraNear));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
vec3 getViewPos(vec2 uv) {
|
|
55
|
+
float d = texture2D(tDepth, uv).r;
|
|
56
|
+
vec4 clipPos = vec4(uv * 2.0 - 1.0, d * 2.0 - 1.0, 1.0);
|
|
57
|
+
vec4 viewPos = projInverseMatrix * clipPos;
|
|
58
|
+
return viewPos.xyz / viewPos.w;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
void main() {
|
|
62
|
+
float depth = texture2D(tDepth, vUv).r;
|
|
63
|
+
if (depth >= 1.0) {
|
|
64
|
+
gl_FragColor = vec4(1.0);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
vec3 viewPos = getViewPos(vUv);
|
|
69
|
+
|
|
70
|
+
// Reconstruct normal from depth buffer
|
|
71
|
+
vec3 dpdx = dFdx(viewPos);
|
|
72
|
+
vec3 dpdy = dFdy(viewPos);
|
|
73
|
+
vec3 normal = normalize(cross(dpdx, dpdy));
|
|
74
|
+
|
|
75
|
+
// Random rotation from noise texture
|
|
76
|
+
vec2 noiseUv = vUv * resolution / 4.0;
|
|
77
|
+
vec3 randomVec = texture2D(tNoise, noiseUv).xyz * 2.0 - 1.0;
|
|
78
|
+
|
|
79
|
+
// Create TBN matrix
|
|
80
|
+
vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
|
|
81
|
+
vec3 bitangent = cross(normal, tangent);
|
|
82
|
+
mat3 TBN = mat3(tangent, bitangent, normal);
|
|
83
|
+
|
|
84
|
+
float occlusion = 0.0;
|
|
85
|
+
|
|
86
|
+
for (int i = 0; i < 128; i++) {
|
|
87
|
+
if (i >= kernelSize) break;
|
|
88
|
+
|
|
89
|
+
// Transform sample to view space
|
|
90
|
+
vec3 samplePos = TBN * kernel[i];
|
|
91
|
+
samplePos = viewPos + samplePos * radius;
|
|
92
|
+
|
|
93
|
+
// Project sample to screen
|
|
94
|
+
vec4 offset = projMatrix * vec4(samplePos, 1.0);
|
|
95
|
+
offset.xyz /= offset.w;
|
|
96
|
+
vec2 sampleUv = offset.xy * 0.5 + 0.5;
|
|
97
|
+
|
|
98
|
+
// Out of screen
|
|
99
|
+
if (sampleUv.x < 0.0 || sampleUv.x > 1.0 || sampleUv.y < 0.0 || sampleUv.y > 1.0) continue;
|
|
100
|
+
|
|
101
|
+
float sampleDepth = linearDepth(texture2D(tDepth, sampleUv).r);
|
|
102
|
+
float rangeCheck = smoothstep(0.0, 1.0, radius / abs(-viewPos.z - sampleDepth));
|
|
103
|
+
|
|
104
|
+
float dist = abs(-viewPos.z - sampleDepth);
|
|
105
|
+
if (dist >= minDistance && dist <= maxDistance) {
|
|
106
|
+
occlusion += (sampleDepth <= -samplePos.z - bias ? 1.0 : 0.0) * rangeCheck;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
occlusion = 1.0 - (occlusion / float(kernelSize)) * intensity;
|
|
111
|
+
gl_FragColor = vec4(vec3(occlusion), 1.0);
|
|
112
|
+
}
|
|
117
113
|
`;
|
|
118
|
-
const BLUR_FRAGMENT = `
|
|
119
|
-
uniform sampler2D tAO;
|
|
120
|
-
uniform sampler2D tDepth;
|
|
121
|
-
uniform vec2 resolution;
|
|
122
|
-
uniform int blurSize;
|
|
123
|
-
uniform float cameraNear;
|
|
124
|
-
uniform float cameraFar;
|
|
125
|
-
|
|
126
|
-
varying vec2 vUv;
|
|
127
|
-
|
|
128
|
-
float linearDepth(float d) {
|
|
129
|
-
return cameraNear * cameraFar / (cameraFar - d * (cameraFar - cameraNear));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
void main() {
|
|
133
|
-
float centerDepth = linearDepth(texture2D(tDepth, vUv).r);
|
|
134
|
-
float result = 0.0;
|
|
135
|
-
float weightSum = 0.0;
|
|
136
|
-
|
|
137
|
-
for (int x = -4; x <= 4; x++) {
|
|
138
|
-
for (int y = -4; y <= 4; y++) {
|
|
139
|
-
if (abs(x) > blurSize || abs(y) > blurSize) continue;
|
|
140
|
-
|
|
141
|
-
vec2 offset = vec2(float(x), float(y)) / resolution;
|
|
142
|
-
float sampleDepth = linearDepth(texture2D(tDepth, vUv + offset).r);
|
|
143
|
-
|
|
144
|
-
// Bilateral weight based on depth difference
|
|
145
|
-
float depthWeight = exp(-abs(centerDepth - sampleDepth) * 10.0);
|
|
146
|
-
float spatialWeight = exp(-float(x * x + y * y) / (2.0 * float(blurSize * blurSize)));
|
|
147
|
-
float weight = depthWeight * spatialWeight;
|
|
148
|
-
|
|
149
|
-
result += texture2D(tAO, vUv + offset).r * weight;
|
|
150
|
-
weightSum += weight;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
gl_FragColor = vec4(vec3(result / weightSum), 1.0);
|
|
155
|
-
}
|
|
114
|
+
const BLUR_FRAGMENT = `
|
|
115
|
+
uniform sampler2D tAO;
|
|
116
|
+
uniform sampler2D tDepth;
|
|
117
|
+
uniform vec2 resolution;
|
|
118
|
+
uniform int blurSize;
|
|
119
|
+
uniform float cameraNear;
|
|
120
|
+
uniform float cameraFar;
|
|
121
|
+
|
|
122
|
+
varying vec2 vUv;
|
|
123
|
+
|
|
124
|
+
float linearDepth(float d) {
|
|
125
|
+
return cameraNear * cameraFar / (cameraFar - d * (cameraFar - cameraNear));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
void main() {
|
|
129
|
+
float centerDepth = linearDepth(texture2D(tDepth, vUv).r);
|
|
130
|
+
float result = 0.0;
|
|
131
|
+
float weightSum = 0.0;
|
|
132
|
+
|
|
133
|
+
for (int x = -4; x <= 4; x++) {
|
|
134
|
+
for (int y = -4; y <= 4; y++) {
|
|
135
|
+
if (abs(x) > blurSize || abs(y) > blurSize) continue;
|
|
136
|
+
|
|
137
|
+
vec2 offset = vec2(float(x), float(y)) / resolution;
|
|
138
|
+
float sampleDepth = linearDepth(texture2D(tDepth, vUv + offset).r);
|
|
139
|
+
|
|
140
|
+
// Bilateral weight based on depth difference
|
|
141
|
+
float depthWeight = exp(-abs(centerDepth - sampleDepth) * 10.0);
|
|
142
|
+
float spatialWeight = exp(-float(x * x + y * y) / (2.0 * float(blurSize * blurSize)));
|
|
143
|
+
float weight = depthWeight * spatialWeight;
|
|
144
|
+
|
|
145
|
+
result += texture2D(tAO, vUv + offset).r * weight;
|
|
146
|
+
weightSum += weight;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
gl_FragColor = vec4(vec3(result / weightSum), 1.0);
|
|
151
|
+
}
|
|
156
152
|
`;
|
|
157
|
-
/* ── Generate kernel and noise ── */
|
|
158
153
|
function generateSSAOKernel(size) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
return kernel;
|
|
154
|
+
const kernel = new Float32Array(size * 3);
|
|
155
|
+
for (let i = 0; i < size; i++) {
|
|
156
|
+
let x = Math.random() * 2 - 1;
|
|
157
|
+
let y = Math.random() * 2 - 1;
|
|
158
|
+
let z = Math.random();
|
|
159
|
+
const len = Math.sqrt(x * x + y * y + z * z);
|
|
160
|
+
x /= len;
|
|
161
|
+
y /= len;
|
|
162
|
+
z /= len;
|
|
163
|
+
let scale = i / size;
|
|
164
|
+
scale = 0.1 + scale * scale * 0.9;
|
|
165
|
+
kernel[i * 3] = x * scale;
|
|
166
|
+
kernel[i * 3 + 1] = y * scale;
|
|
167
|
+
kernel[i * 3 + 2] = z * scale;
|
|
168
|
+
}
|
|
169
|
+
return kernel;
|
|
177
170
|
}
|
|
178
171
|
function generateNoiseTexture() {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
172
|
+
const size = 4;
|
|
173
|
+
const data = new Float32Array(size * size * 4);
|
|
174
|
+
for (let i = 0; i < size * size; i++) {
|
|
175
|
+
data[i * 4] = Math.random() * 2 - 1;
|
|
176
|
+
data[i * 4 + 1] = Math.random() * 2 - 1;
|
|
177
|
+
data[i * 4 + 2] = 0;
|
|
178
|
+
data[i * 4 + 3] = 1;
|
|
179
|
+
}
|
|
180
|
+
const tex = new THREE__namespace.DataTexture(data, size, size, THREE__namespace.RGBAFormat, THREE__namespace.FloatType);
|
|
181
|
+
tex.wrapS = THREE__namespace.RepeatWrapping;
|
|
182
|
+
tex.wrapT = THREE__namespace.RepeatWrapping;
|
|
183
|
+
tex.needsUpdate = true;
|
|
184
|
+
return tex;
|
|
192
185
|
}
|
|
193
|
-
/* ── Hook ── */
|
|
194
186
|
const DEFAULT_SSAO = {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
187
|
+
enabled: true,
|
|
188
|
+
mode: "ssao",
|
|
189
|
+
samples: 32,
|
|
190
|
+
radius: 1,
|
|
191
|
+
bias: 0.025,
|
|
192
|
+
intensity: 1.5,
|
|
193
|
+
resolution: 0.5,
|
|
194
|
+
blurEnabled: true,
|
|
195
|
+
blurSize: 2,
|
|
196
|
+
minDistance: 0.01,
|
|
197
|
+
maxDistance: 10
|
|
206
198
|
};
|
|
207
199
|
function useSSAO(renderer, scene, camera, configOverride) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
200
|
+
const [config, setConfigState] = React.useState({ ...DEFAULT_SSAO, ...configOverride });
|
|
201
|
+
const [aoRenderTarget, setAoRenderTarget] = React.useState(null);
|
|
202
|
+
const depthRT = React.useRef(null);
|
|
203
|
+
const blurRT = React.useRef(null);
|
|
204
|
+
const ssaoMaterial = React.useRef(null);
|
|
205
|
+
const blurMaterial = React.useRef(null);
|
|
206
|
+
const noiseTexture = React.useRef(generateNoiseTexture());
|
|
207
|
+
const kernel = React.useRef(generateSSAOKernel(128));
|
|
208
|
+
const orthoScene = React.useRef(new THREE__namespace.Scene());
|
|
209
|
+
const orthoCamera = React.useRef(new THREE__namespace.OrthographicCamera(-1, 1, 1, -1, 0, 1));
|
|
210
|
+
const quadRef = React.useRef(null);
|
|
211
|
+
const setConfig = React.useCallback((partial) => {
|
|
212
|
+
setConfigState((prev) => ({ ...prev, ...partial }));
|
|
213
|
+
}, []);
|
|
214
|
+
React.useEffect(() => {
|
|
215
|
+
if (!renderer || !camera) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const width = Math.floor(renderer.domElement.width * config.resolution);
|
|
219
|
+
const height = Math.floor(renderer.domElement.height * config.resolution);
|
|
220
|
+
const dRT = new THREE__namespace.WebGLRenderTarget(width, height, {
|
|
221
|
+
minFilter: THREE__namespace.NearestFilter,
|
|
222
|
+
magFilter: THREE__namespace.NearestFilter,
|
|
223
|
+
type: THREE__namespace.FloatType
|
|
224
|
+
});
|
|
225
|
+
dRT.depthTexture = new THREE__namespace.DepthTexture(width, height);
|
|
226
|
+
dRT.depthTexture.type = THREE__namespace.UnsignedIntType;
|
|
227
|
+
depthRT.current = dRT;
|
|
228
|
+
const aoRT = new THREE__namespace.WebGLRenderTarget(width, height, {
|
|
229
|
+
minFilter: THREE__namespace.LinearFilter,
|
|
230
|
+
magFilter: THREE__namespace.LinearFilter
|
|
231
|
+
});
|
|
232
|
+
setAoRenderTarget(aoRT);
|
|
233
|
+
const bRT = new THREE__namespace.WebGLRenderTarget(width, height, {
|
|
234
|
+
minFilter: THREE__namespace.LinearFilter,
|
|
235
|
+
magFilter: THREE__namespace.LinearFilter
|
|
236
|
+
});
|
|
237
|
+
blurRT.current = bRT;
|
|
238
|
+
const kernelUniforms = [];
|
|
239
|
+
for (let i = 0; i < 128; i++) {
|
|
240
|
+
kernelUniforms.push(
|
|
241
|
+
new THREE__namespace.Vector3(
|
|
242
|
+
kernel.current[i * 3],
|
|
243
|
+
kernel.current[i * 3 + 1],
|
|
244
|
+
kernel.current[i * 3 + 2]
|
|
245
|
+
)
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
const ssaoMat = new THREE__namespace.ShaderMaterial({
|
|
249
|
+
vertexShader: SSAO_VERTEX,
|
|
250
|
+
fragmentShader: SSAO_FRAGMENT,
|
|
251
|
+
uniforms: {
|
|
252
|
+
tDepth: { value: dRT.depthTexture },
|
|
253
|
+
tNoise: { value: noiseTexture.current },
|
|
254
|
+
kernel: { value: kernelUniforms },
|
|
255
|
+
kernelSize: { value: config.samples },
|
|
256
|
+
resolution: { value: new THREE__namespace.Vector2(width, height) },
|
|
257
|
+
projMatrix: { value: camera.projectionMatrix },
|
|
258
|
+
projInverseMatrix: { value: camera.projectionMatrixInverse },
|
|
259
|
+
cameraNear: { value: camera.near },
|
|
260
|
+
cameraFar: { value: camera.far },
|
|
261
|
+
radius: { value: config.radius },
|
|
262
|
+
bias: { value: config.bias },
|
|
263
|
+
intensity: { value: config.intensity },
|
|
264
|
+
minDistance: { value: config.minDistance },
|
|
265
|
+
maxDistance: { value: config.maxDistance }
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
ssaoMaterial.current = ssaoMat;
|
|
269
|
+
const blurMat = new THREE__namespace.ShaderMaterial({
|
|
270
|
+
vertexShader: SSAO_VERTEX,
|
|
271
|
+
fragmentShader: BLUR_FRAGMENT,
|
|
272
|
+
uniforms: {
|
|
273
|
+
tAO: { value: aoRT.texture },
|
|
274
|
+
tDepth: { value: dRT.depthTexture },
|
|
275
|
+
resolution: { value: new THREE__namespace.Vector2(width, height) },
|
|
276
|
+
blurSize: { value: config.blurSize },
|
|
277
|
+
cameraNear: { value: camera.near },
|
|
278
|
+
cameraFar: { value: camera.far }
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
blurMaterial.current = blurMat;
|
|
282
|
+
const quad = new THREE__namespace.Mesh(new THREE__namespace.PlaneGeometry(2, 2), ssaoMat);
|
|
283
|
+
quad.frustumCulled = false;
|
|
284
|
+
const ortho = orthoScene.current;
|
|
285
|
+
ortho.add(quad);
|
|
286
|
+
quadRef.current = quad;
|
|
287
|
+
return () => {
|
|
288
|
+
dRT.dispose();
|
|
289
|
+
aoRT.dispose();
|
|
290
|
+
bRT.dispose();
|
|
291
|
+
ssaoMat.dispose();
|
|
292
|
+
blurMat.dispose();
|
|
293
|
+
ortho.remove(quad);
|
|
294
|
+
};
|
|
295
|
+
}, [renderer, camera, config.resolution]);
|
|
296
|
+
React.useEffect(() => {
|
|
297
|
+
if (!ssaoMaterial.current) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
const u = ssaoMaterial.current.uniforms;
|
|
301
|
+
u.kernelSize.value = config.samples;
|
|
302
|
+
u.radius.value = config.radius;
|
|
303
|
+
u.bias.value = config.bias;
|
|
304
|
+
u.intensity.value = config.intensity;
|
|
305
|
+
u.minDistance.value = config.minDistance;
|
|
306
|
+
u.maxDistance.value = config.maxDistance;
|
|
307
|
+
}, [config]);
|
|
308
|
+
React.useEffect(() => {
|
|
309
|
+
if (!blurMaterial.current) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
blurMaterial.current.uniforms.blurSize.value = config.blurSize;
|
|
313
|
+
}, [config.blurSize]);
|
|
314
|
+
const update = React.useCallback(() => {
|
|
315
|
+
if (!renderer || !scene || !camera || !config.enabled) {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (!depthRT.current || !aoRenderTarget || !quadRef.current) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
renderer.setRenderTarget(depthRT.current);
|
|
322
|
+
renderer.render(scene, camera);
|
|
323
|
+
quadRef.current.material = ssaoMaterial.current;
|
|
324
|
+
renderer.setRenderTarget(aoRenderTarget);
|
|
325
|
+
renderer.render(orthoScene.current, orthoCamera.current);
|
|
326
|
+
if (config.blurEnabled && blurMaterial.current && blurRT.current) {
|
|
327
|
+
blurMaterial.current.uniforms.tAO.value = aoRenderTarget.texture;
|
|
328
|
+
quadRef.current.material = blurMaterial.current;
|
|
329
|
+
renderer.setRenderTarget(blurRT.current);
|
|
330
|
+
renderer.render(orthoScene.current, orthoCamera.current);
|
|
331
|
+
}
|
|
332
|
+
renderer.setRenderTarget(null);
|
|
333
|
+
}, [renderer, scene, camera, config.enabled, config.blurEnabled, aoRenderTarget]);
|
|
334
|
+
const dispose = React.useCallback(() => {
|
|
335
|
+
depthRT.current?.dispose();
|
|
336
|
+
aoRenderTarget?.dispose();
|
|
337
|
+
blurRT.current?.dispose();
|
|
338
|
+
ssaoMaterial.current?.dispose();
|
|
339
|
+
blurMaterial.current?.dispose();
|
|
340
|
+
noiseTexture.current?.dispose();
|
|
341
|
+
}, [aoRenderTarget]);
|
|
342
|
+
return { config, setConfig, aoRenderTarget, update, dispose };
|
|
343
|
+
}
|
|
344
|
+
const NiceSSAO = ({
|
|
345
|
+
renderer,
|
|
346
|
+
scene,
|
|
347
|
+
camera,
|
|
348
|
+
config: configProp,
|
|
349
|
+
className = ""
|
|
350
|
+
}) => {
|
|
351
|
+
const { t } = i18n.useNiceTranslation();
|
|
352
|
+
const { config, setConfig } = useSSAO(renderer, scene, camera, configProp);
|
|
353
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `nice-ssao ${className}`, style: { display: "grid", gap: 8, fontSize: 13 }, children: [
|
|
354
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
|
|
355
|
+
/* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
|
|
356
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "circle", size: 14 }),
|
|
357
|
+
" ",
|
|
358
|
+
t("ssao.ambientOcclusion", "Ambient Occlusion")
|
|
359
|
+
] }),
|
|
360
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { style: { display: "flex", alignItems: "center", gap: 4, fontSize: 11 }, children: [
|
|
361
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
362
|
+
"input",
|
|
363
|
+
{
|
|
364
|
+
type: "checkbox",
|
|
365
|
+
checked: config.enabled,
|
|
366
|
+
onChange: (e) => setConfig({ enabled: e.target.checked })
|
|
367
|
+
}
|
|
368
|
+
),
|
|
369
|
+
t("ssao.enabled", "Enabled")
|
|
370
|
+
] })
|
|
371
|
+
] }),
|
|
372
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
373
|
+
t("ssao.mode", "Mode:"),
|
|
374
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
375
|
+
"select",
|
|
376
|
+
{
|
|
377
|
+
value: config.mode,
|
|
378
|
+
onChange: (e) => setConfig({ mode: e.target.value }),
|
|
379
|
+
style: { width: "100%", marginTop: 2 },
|
|
380
|
+
children: [
|
|
381
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "ssao", children: t("ssao.ssao", "SSAO") }),
|
|
382
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "hbao", children: t("ssao.hbao", "HBAO") })
|
|
383
|
+
]
|
|
226
384
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
magFilter: THREE__namespace.LinearFilter,
|
|
242
|
-
});
|
|
243
|
-
setAoRenderTarget(aoRT);
|
|
244
|
-
// Blur render target
|
|
245
|
-
const bRT = new THREE__namespace.WebGLRenderTarget(width, height, {
|
|
246
|
-
minFilter: THREE__namespace.LinearFilter,
|
|
247
|
-
magFilter: THREE__namespace.LinearFilter,
|
|
248
|
-
});
|
|
249
|
-
blurRT.current = bRT;
|
|
250
|
-
// Kernel uniform as vec3 array
|
|
251
|
-
const kernelUniforms = [];
|
|
252
|
-
for (let i = 0; i < 128; i++) {
|
|
253
|
-
kernelUniforms.push(new THREE__namespace.Vector3(kernel.current[i * 3], kernel.current[i * 3 + 1], kernel.current[i * 3 + 2]));
|
|
385
|
+
)
|
|
386
|
+
] }),
|
|
387
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
388
|
+
t("ssao.samples", "Samples: {samples}").replace("{samples}", String(config.samples)),
|
|
389
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
390
|
+
"input",
|
|
391
|
+
{
|
|
392
|
+
type: "range",
|
|
393
|
+
min: 8,
|
|
394
|
+
max: 128,
|
|
395
|
+
step: 8,
|
|
396
|
+
value: config.samples,
|
|
397
|
+
onChange: (e) => setConfig({ samples: parseInt(e.target.value, 10) }),
|
|
398
|
+
style: { width: "100%" }
|
|
254
399
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
radius: { value: config.radius },
|
|
270
|
-
bias: { value: config.bias },
|
|
271
|
-
intensity: { value: config.intensity },
|
|
272
|
-
minDistance: { value: config.minDistance },
|
|
273
|
-
maxDistance: { value: config.maxDistance },
|
|
274
|
-
},
|
|
275
|
-
});
|
|
276
|
-
ssaoMaterial.current = ssaoMat;
|
|
277
|
-
// Blur material
|
|
278
|
-
const blurMat = new THREE__namespace.ShaderMaterial({
|
|
279
|
-
vertexShader: SSAO_VERTEX,
|
|
280
|
-
fragmentShader: BLUR_FRAGMENT,
|
|
281
|
-
uniforms: {
|
|
282
|
-
tAO: { value: aoRT.texture },
|
|
283
|
-
tDepth: { value: dRT.depthTexture },
|
|
284
|
-
resolution: { value: new THREE__namespace.Vector2(width, height) },
|
|
285
|
-
blurSize: { value: config.blurSize },
|
|
286
|
-
cameraNear: { value: camera.near },
|
|
287
|
-
cameraFar: { value: camera.far },
|
|
288
|
-
},
|
|
289
|
-
});
|
|
290
|
-
blurMaterial.current = blurMat;
|
|
291
|
-
// Full-screen quad
|
|
292
|
-
const quad = new THREE__namespace.Mesh(new THREE__namespace.PlaneGeometry(2, 2), ssaoMat);
|
|
293
|
-
quad.frustumCulled = false;
|
|
294
|
-
const ortho = orthoScene.current;
|
|
295
|
-
ortho.add(quad);
|
|
296
|
-
quadRef.current = quad;
|
|
297
|
-
return () => {
|
|
298
|
-
dRT.dispose();
|
|
299
|
-
aoRT.dispose();
|
|
300
|
-
bRT.dispose();
|
|
301
|
-
ssaoMat.dispose();
|
|
302
|
-
blurMat.dispose();
|
|
303
|
-
ortho.remove(quad);
|
|
304
|
-
};
|
|
305
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps -- the uniforms' first values; the next effect updates them without rebuilding the render targets
|
|
306
|
-
}, [renderer, camera, config.resolution]);
|
|
307
|
-
// Update uniforms
|
|
308
|
-
React.useEffect(() => {
|
|
309
|
-
if (!ssaoMaterial.current) {
|
|
310
|
-
return;
|
|
400
|
+
)
|
|
401
|
+
] }),
|
|
402
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
403
|
+
t("ssao.radius", "Radius: {radius}").replace("{radius}", String(config.radius.toFixed(2))),
|
|
404
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
405
|
+
"input",
|
|
406
|
+
{
|
|
407
|
+
type: "range",
|
|
408
|
+
min: 0.1,
|
|
409
|
+
max: 5,
|
|
410
|
+
step: 0.1,
|
|
411
|
+
value: config.radius,
|
|
412
|
+
onChange: (e) => setConfig({ radius: parseFloat(e.target.value) }),
|
|
413
|
+
style: { width: "100%" }
|
|
311
414
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
415
|
+
)
|
|
416
|
+
] }),
|
|
417
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
418
|
+
t("ssao.intensity", "Intensity: {intensity}").replace(
|
|
419
|
+
"{intensity}",
|
|
420
|
+
String(config.intensity.toFixed(2))
|
|
421
|
+
),
|
|
422
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
423
|
+
"input",
|
|
424
|
+
{
|
|
425
|
+
type: "range",
|
|
426
|
+
min: 0,
|
|
427
|
+
max: 3,
|
|
428
|
+
step: 0.1,
|
|
429
|
+
value: config.intensity,
|
|
430
|
+
onChange: (e) => setConfig({ intensity: parseFloat(e.target.value) }),
|
|
431
|
+
style: { width: "100%" }
|
|
323
432
|
}
|
|
324
|
-
|
|
325
|
-
},
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
433
|
+
)
|
|
434
|
+
] }),
|
|
435
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
436
|
+
t("ssao.bias", "Bias: {bias}").replace("{bias}", String(config.bias.toFixed(3))),
|
|
437
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
438
|
+
"input",
|
|
439
|
+
{
|
|
440
|
+
type: "range",
|
|
441
|
+
min: 1e-3,
|
|
442
|
+
max: 0.1,
|
|
443
|
+
step: 1e-3,
|
|
444
|
+
value: config.bias,
|
|
445
|
+
onChange: (e) => setConfig({ bias: parseFloat(e.target.value) }),
|
|
446
|
+
style: { width: "100%" }
|
|
329
447
|
}
|
|
330
|
-
|
|
331
|
-
|
|
448
|
+
)
|
|
449
|
+
] }),
|
|
450
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
451
|
+
t("ssao.resolution", "Resolution: {resolution}").replace(
|
|
452
|
+
"{resolution}",
|
|
453
|
+
String(config.resolution.toFixed(2))
|
|
454
|
+
),
|
|
455
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
456
|
+
"input",
|
|
457
|
+
{
|
|
458
|
+
type: "range",
|
|
459
|
+
min: 0.25,
|
|
460
|
+
max: 1,
|
|
461
|
+
step: 0.25,
|
|
462
|
+
value: config.resolution,
|
|
463
|
+
onChange: (e) => setConfig({ resolution: parseFloat(e.target.value) }),
|
|
464
|
+
style: { width: "100%" }
|
|
332
465
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
blurMaterial.current.uniforms.tAO.value = aoRenderTarget.texture;
|
|
343
|
-
quadRef.current.material = blurMaterial.current;
|
|
344
|
-
renderer.setRenderTarget(blurRT.current);
|
|
345
|
-
renderer.render(orthoScene.current, orthoCamera.current);
|
|
466
|
+
)
|
|
467
|
+
] }),
|
|
468
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
469
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
470
|
+
"input",
|
|
471
|
+
{
|
|
472
|
+
type: "checkbox",
|
|
473
|
+
checked: config.blurEnabled,
|
|
474
|
+
onChange: (e) => setConfig({ blurEnabled: e.target.checked })
|
|
346
475
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
(_c = ssaoMaterial.current) === null || _c === void 0 ? void 0 : _c.dispose();
|
|
355
|
-
(_d = blurMaterial.current) === null || _d === void 0 ? void 0 : _d.dispose();
|
|
356
|
-
(_e = noiseTexture.current) === null || _e === void 0 ? void 0 : _e.dispose();
|
|
357
|
-
}, [aoRenderTarget]);
|
|
358
|
-
return { config, setConfig, aoRenderTarget, update, dispose };
|
|
359
|
-
}
|
|
360
|
-
/* ── Component ── */
|
|
361
|
-
const NiceSSAO = ({ renderer, scene, camera, config: configProp, className = '', }) => {
|
|
362
|
-
const { t } = i18n.useNiceTranslation();
|
|
363
|
-
const { config, setConfig } = useSSAO(renderer, scene, camera, configProp);
|
|
364
|
-
return (jsxRuntime.jsxs("div", { className: `nice-ssao ${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: "circle", size: 14 }), " ", t('ssao.ambientOcclusion', 'Ambient Occlusion')] }), 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('ssao.enabled', 'Enabled')] })] }), jsxRuntime.jsxs("label", { children: [t('ssao.mode', 'Mode:'), jsxRuntime.jsxs("select", { value: config.mode, onChange: (e) => setConfig({ mode: e.target.value }), style: { width: '100%', marginTop: 2 }, children: [jsxRuntime.jsx("option", { value: "ssao", children: t('ssao.ssao', 'SSAO') }), jsxRuntime.jsx("option", { value: "hbao", children: t('ssao.hbao', 'HBAO') })] })] }), jsxRuntime.jsxs("label", { children: [t('ssao.samples', 'Samples: {samples}').replace('{samples}', String(config.samples)), jsxRuntime.jsx("input", { type: "range", min: 8, max: 128, step: 8, value: config.samples, onChange: (e) => setConfig({ samples: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('ssao.radius', 'Radius: {radius}').replace('{radius}', String(config.radius.toFixed(2))), jsxRuntime.jsx("input", { type: "range", min: 0.1, max: 5, step: 0.1, value: config.radius, onChange: (e) => setConfig({ radius: parseFloat(e.target.value) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('ssao.intensity', 'Intensity: {intensity}').replace('{intensity}', String(config.intensity.toFixed(2))), jsxRuntime.jsx("input", { type: "range", min: 0, max: 3, step: 0.1, value: config.intensity, onChange: (e) => setConfig({ intensity: parseFloat(e.target.value) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('ssao.bias', 'Bias: {bias}').replace('{bias}', String(config.bias.toFixed(3))), jsxRuntime.jsx("input", { type: "range", min: 0.001, max: 0.1, step: 0.001, value: config.bias, onChange: (e) => setConfig({ bias: parseFloat(e.target.value) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('ssao.resolution', 'Resolution: {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", { style: { display: 'flex', alignItems: 'center', gap: 6 }, children: [jsxRuntime.jsx("input", { type: "checkbox", checked: config.blurEnabled, onChange: (e) => setConfig({ blurEnabled: e.target.checked }) }), t('ssao.bilateralBlurSize', 'Bilateral Blur (size: {blurSize})').replace('{blurSize}', String(config.blurSize))] })] }));
|
|
476
|
+
),
|
|
477
|
+
t("ssao.bilateralBlurSize", "Bilateral Blur (size: {blurSize})").replace(
|
|
478
|
+
"{blurSize}",
|
|
479
|
+
String(config.blurSize)
|
|
480
|
+
)
|
|
481
|
+
] })
|
|
482
|
+
] });
|
|
365
483
|
};
|
|
366
|
-
|
|
367
484
|
exports.NiceSSAO = NiceSSAO;
|
|
368
485
|
exports.useSSAO = useSSAO;
|