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