@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,263 +1,394 @@
|
|
|
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 SSR_VERTEX = `
|
|
7
|
+
varying vec2 vUv;
|
|
8
|
+
void main() {
|
|
9
|
+
vUv = uv;
|
|
10
|
+
gl_Position = vec4(position, 1.0);
|
|
11
|
+
}
|
|
14
12
|
`;
|
|
15
|
-
const SSR_FRAGMENT = `
|
|
16
|
-
uniform sampler2D tDiffuse;
|
|
17
|
-
uniform sampler2D tDepth;
|
|
18
|
-
uniform sampler2D tNormal;
|
|
19
|
-
uniform mat4 projMatrix;
|
|
20
|
-
uniform mat4 projInverseMatrix;
|
|
21
|
-
uniform mat4 viewMatrix;
|
|
22
|
-
uniform vec2 resolution;
|
|
23
|
-
uniform float cameraNear;
|
|
24
|
-
uniform float cameraFar;
|
|
25
|
-
uniform int maxSteps;
|
|
26
|
-
uniform float maxDistance;
|
|
27
|
-
uniform float thickness;
|
|
28
|
-
uniform float jitter;
|
|
29
|
-
uniform float intensity;
|
|
30
|
-
uniform float fresnelExponent;
|
|
31
|
-
|
|
32
|
-
varying vec2 vUv;
|
|
33
|
-
|
|
34
|
-
float getDepth(vec2 uv) {
|
|
35
|
-
float d = texture2D(tDepth, uv).r;
|
|
36
|
-
return cameraNear * cameraFar / (cameraFar - d * (cameraFar - cameraNear));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
vec3 getViewPosition(vec2 uv, float depth) {
|
|
40
|
-
vec4 clipPos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
|
41
|
-
vec4 viewPos = projInverseMatrix * clipPos;
|
|
42
|
-
return viewPos.xyz / viewPos.w;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
vec3 getViewNormal(vec2 uv) {
|
|
46
|
-
return normalize(texture2D(tNormal, uv).xyz * 2.0 - 1.0);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
float fresnel(vec3 viewDir, vec3 normal, float exponent) {
|
|
50
|
-
return pow(1.0 - max(dot(-viewDir, normal), 0.0), exponent);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
vec2 rayMarch(vec3 origin, vec3 direction) {
|
|
54
|
-
vec3 pos = origin;
|
|
55
|
-
float stepSize = maxDistance / float(maxSteps);
|
|
56
|
-
|
|
57
|
-
for (int i = 0; i < 256; i++) {
|
|
58
|
-
if (i >= maxSteps) break;
|
|
59
|
-
|
|
60
|
-
pos += direction * stepSize;
|
|
61
|
-
|
|
62
|
-
// Project to screen space
|
|
63
|
-
vec4 projPos = projMatrix * vec4(pos, 1.0);
|
|
64
|
-
projPos.xyz /= projPos.w;
|
|
65
|
-
vec2 screenUv = projPos.xy * 0.5 + 0.5;
|
|
66
|
-
|
|
67
|
-
// Out of screen
|
|
68
|
-
if (screenUv.x < 0.0 || screenUv.x > 1.0 || screenUv.y < 0.0 || screenUv.y > 1.0) {
|
|
69
|
-
return vec2(-1.0);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
float sceneDepth = getDepth(screenUv);
|
|
73
|
-
float rayDepth = -pos.z;
|
|
74
|
-
|
|
75
|
-
if (rayDepth > sceneDepth && rayDepth - sceneDepth < thickness) {
|
|
76
|
-
return screenUv;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return vec2(-1.0);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
void main() {
|
|
84
|
-
vec4 baseColor = texture2D(tDiffuse, vUv);
|
|
85
|
-
float depth = texture2D(tDepth, vUv).r;
|
|
86
|
-
|
|
87
|
-
if (depth >= 1.0) {
|
|
88
|
-
gl_FragColor = baseColor;
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
vec3 viewPos = getViewPosition(vUv, depth);
|
|
93
|
-
vec3 viewNormal = getViewNormal(vUv);
|
|
94
|
-
vec3 viewDir = normalize(viewPos);
|
|
95
|
-
|
|
96
|
-
// Reflect view direction around normal
|
|
97
|
-
vec3 reflectDir = reflect(viewDir, viewNormal);
|
|
98
|
-
|
|
99
|
-
// Add jitter
|
|
100
|
-
float j = fract(sin(dot(vUv, vec2(12.9898, 78.233))) * 43758.5453) * jitter;
|
|
101
|
-
reflectDir += j * 0.01;
|
|
102
|
-
reflectDir = normalize(reflectDir);
|
|
103
|
-
|
|
104
|
-
// Ray march
|
|
105
|
-
vec2 hitUv = rayMarch(viewPos + viewNormal * 0.01, reflectDir);
|
|
106
|
-
|
|
107
|
-
vec3 reflection = vec3(0.0);
|
|
108
|
-
if (hitUv.x >= 0.0) {
|
|
109
|
-
reflection = texture2D(tDiffuse, hitUv).rgb;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Fresnel attenuation
|
|
113
|
-
float f = fresnel(viewDir, viewNormal, fresnelExponent);
|
|
114
|
-
|
|
115
|
-
gl_FragColor = vec4(mix(baseColor.rgb, reflection, f * intensity), baseColor.a);
|
|
116
|
-
}
|
|
13
|
+
const SSR_FRAGMENT = `
|
|
14
|
+
uniform sampler2D tDiffuse;
|
|
15
|
+
uniform sampler2D tDepth;
|
|
16
|
+
uniform sampler2D tNormal;
|
|
17
|
+
uniform mat4 projMatrix;
|
|
18
|
+
uniform mat4 projInverseMatrix;
|
|
19
|
+
uniform mat4 viewMatrix;
|
|
20
|
+
uniform vec2 resolution;
|
|
21
|
+
uniform float cameraNear;
|
|
22
|
+
uniform float cameraFar;
|
|
23
|
+
uniform int maxSteps;
|
|
24
|
+
uniform float maxDistance;
|
|
25
|
+
uniform float thickness;
|
|
26
|
+
uniform float jitter;
|
|
27
|
+
uniform float intensity;
|
|
28
|
+
uniform float fresnelExponent;
|
|
29
|
+
|
|
30
|
+
varying vec2 vUv;
|
|
31
|
+
|
|
32
|
+
float getDepth(vec2 uv) {
|
|
33
|
+
float d = texture2D(tDepth, uv).r;
|
|
34
|
+
return cameraNear * cameraFar / (cameraFar - d * (cameraFar - cameraNear));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
vec3 getViewPosition(vec2 uv, float depth) {
|
|
38
|
+
vec4 clipPos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
|
39
|
+
vec4 viewPos = projInverseMatrix * clipPos;
|
|
40
|
+
return viewPos.xyz / viewPos.w;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
vec3 getViewNormal(vec2 uv) {
|
|
44
|
+
return normalize(texture2D(tNormal, uv).xyz * 2.0 - 1.0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
float fresnel(vec3 viewDir, vec3 normal, float exponent) {
|
|
48
|
+
return pow(1.0 - max(dot(-viewDir, normal), 0.0), exponent);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
vec2 rayMarch(vec3 origin, vec3 direction) {
|
|
52
|
+
vec3 pos = origin;
|
|
53
|
+
float stepSize = maxDistance / float(maxSteps);
|
|
54
|
+
|
|
55
|
+
for (int i = 0; i < 256; i++) {
|
|
56
|
+
if (i >= maxSteps) break;
|
|
57
|
+
|
|
58
|
+
pos += direction * stepSize;
|
|
59
|
+
|
|
60
|
+
// Project to screen space
|
|
61
|
+
vec4 projPos = projMatrix * vec4(pos, 1.0);
|
|
62
|
+
projPos.xyz /= projPos.w;
|
|
63
|
+
vec2 screenUv = projPos.xy * 0.5 + 0.5;
|
|
64
|
+
|
|
65
|
+
// Out of screen
|
|
66
|
+
if (screenUv.x < 0.0 || screenUv.x > 1.0 || screenUv.y < 0.0 || screenUv.y > 1.0) {
|
|
67
|
+
return vec2(-1.0);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
float sceneDepth = getDepth(screenUv);
|
|
71
|
+
float rayDepth = -pos.z;
|
|
72
|
+
|
|
73
|
+
if (rayDepth > sceneDepth && rayDepth - sceneDepth < thickness) {
|
|
74
|
+
return screenUv;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return vec2(-1.0);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
void main() {
|
|
82
|
+
vec4 baseColor = texture2D(tDiffuse, vUv);
|
|
83
|
+
float depth = texture2D(tDepth, vUv).r;
|
|
84
|
+
|
|
85
|
+
if (depth >= 1.0) {
|
|
86
|
+
gl_FragColor = baseColor;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
vec3 viewPos = getViewPosition(vUv, depth);
|
|
91
|
+
vec3 viewNormal = getViewNormal(vUv);
|
|
92
|
+
vec3 viewDir = normalize(viewPos);
|
|
93
|
+
|
|
94
|
+
// Reflect view direction around normal
|
|
95
|
+
vec3 reflectDir = reflect(viewDir, viewNormal);
|
|
96
|
+
|
|
97
|
+
// Add jitter
|
|
98
|
+
float j = fract(sin(dot(vUv, vec2(12.9898, 78.233))) * 43758.5453) * jitter;
|
|
99
|
+
reflectDir += j * 0.01;
|
|
100
|
+
reflectDir = normalize(reflectDir);
|
|
101
|
+
|
|
102
|
+
// Ray march
|
|
103
|
+
vec2 hitUv = rayMarch(viewPos + viewNormal * 0.01, reflectDir);
|
|
104
|
+
|
|
105
|
+
vec3 reflection = vec3(0.0);
|
|
106
|
+
if (hitUv.x >= 0.0) {
|
|
107
|
+
reflection = texture2D(tDiffuse, hitUv).rgb;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Fresnel attenuation
|
|
111
|
+
float f = fresnel(viewDir, viewNormal, fresnelExponent);
|
|
112
|
+
|
|
113
|
+
gl_FragColor = vec4(mix(baseColor.rgb, reflection, f * intensity), baseColor.a);
|
|
114
|
+
}
|
|
117
115
|
`;
|
|
118
|
-
/* ── Hook ── */
|
|
119
116
|
const DEFAULT_SSR = {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
117
|
+
enabled: true,
|
|
118
|
+
maxSteps: 64,
|
|
119
|
+
maxDistance: 50,
|
|
120
|
+
thickness: 0.5,
|
|
121
|
+
resolution: 0.5,
|
|
122
|
+
jitter: 0.3,
|
|
123
|
+
intensity: 0.6,
|
|
124
|
+
roughnessFade: 0.8,
|
|
125
|
+
fresnelExponent: 3
|
|
129
126
|
};
|
|
130
127
|
function useSSR(renderer, scene, camera, configOverride) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
128
|
+
const [config, setConfigState] = useState({ ...DEFAULT_SSR, ...configOverride });
|
|
129
|
+
const [renderTarget, setRenderTarget] = useState(null);
|
|
130
|
+
const depthTarget = useRef(null);
|
|
131
|
+
const normalTarget = useRef(null);
|
|
132
|
+
const ssrMaterial = useRef(null);
|
|
133
|
+
const fullScreenQuad = useRef(null);
|
|
134
|
+
const orthoScene = useRef(new THREE.Scene());
|
|
135
|
+
const orthoCamera = useRef(new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1));
|
|
136
|
+
const setConfig = useCallback((partial) => {
|
|
137
|
+
setConfigState((prev) => ({ ...prev, ...partial }));
|
|
138
|
+
}, []);
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
if (!renderer || !camera) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const width = Math.floor(renderer.domElement.width * config.resolution);
|
|
144
|
+
const height = Math.floor(renderer.domElement.height * config.resolution);
|
|
145
|
+
const sceneRT = new THREE.WebGLRenderTarget(width, height, {
|
|
146
|
+
minFilter: THREE.LinearFilter,
|
|
147
|
+
magFilter: THREE.LinearFilter,
|
|
148
|
+
format: THREE.RGBAFormat,
|
|
149
|
+
type: THREE.HalfFloatType
|
|
150
|
+
});
|
|
151
|
+
setRenderTarget(sceneRT);
|
|
152
|
+
const dTarget = new THREE.WebGLRenderTarget(width, height, {
|
|
153
|
+
minFilter: THREE.NearestFilter,
|
|
154
|
+
magFilter: THREE.NearestFilter,
|
|
155
|
+
format: THREE.RGBAFormat,
|
|
156
|
+
type: THREE.FloatType
|
|
157
|
+
});
|
|
158
|
+
dTarget.depthTexture = new THREE.DepthTexture(width, height);
|
|
159
|
+
dTarget.depthTexture.type = THREE.UnsignedIntType;
|
|
160
|
+
depthTarget.current = dTarget;
|
|
161
|
+
const nTarget = new THREE.WebGLRenderTarget(width, height, {
|
|
162
|
+
minFilter: THREE.NearestFilter,
|
|
163
|
+
magFilter: THREE.NearestFilter,
|
|
164
|
+
format: THREE.RGBAFormat
|
|
165
|
+
});
|
|
166
|
+
normalTarget.current = nTarget;
|
|
167
|
+
const material = new THREE.ShaderMaterial({
|
|
168
|
+
vertexShader: SSR_VERTEX,
|
|
169
|
+
fragmentShader: SSR_FRAGMENT,
|
|
170
|
+
uniforms: {
|
|
171
|
+
tDiffuse: { value: sceneRT.texture },
|
|
172
|
+
tDepth: { value: dTarget.depthTexture },
|
|
173
|
+
tNormal: { value: nTarget.texture },
|
|
174
|
+
projMatrix: { value: camera.projectionMatrix },
|
|
175
|
+
projInverseMatrix: { value: camera.projectionMatrixInverse },
|
|
176
|
+
viewMatrix: { value: camera.matrixWorldInverse },
|
|
177
|
+
resolution: { value: new THREE.Vector2(width, height) },
|
|
178
|
+
cameraNear: { value: camera.near },
|
|
179
|
+
cameraFar: { value: camera.far },
|
|
180
|
+
maxSteps: { value: config.maxSteps },
|
|
181
|
+
maxDistance: { value: config.maxDistance },
|
|
182
|
+
thickness: { value: config.thickness },
|
|
183
|
+
jitter: { value: config.jitter },
|
|
184
|
+
intensity: { value: config.intensity },
|
|
185
|
+
fresnelExponent: { value: config.fresnelExponent }
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
ssrMaterial.current = material;
|
|
189
|
+
const quad = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), material);
|
|
190
|
+
quad.frustumCulled = false;
|
|
191
|
+
const ortho = orthoScene.current;
|
|
192
|
+
ortho.add(quad);
|
|
193
|
+
fullScreenQuad.current = quad;
|
|
194
|
+
return () => {
|
|
195
|
+
sceneRT.dispose();
|
|
196
|
+
dTarget.dispose();
|
|
197
|
+
nTarget.dispose();
|
|
198
|
+
material.dispose();
|
|
199
|
+
ortho.remove(quad);
|
|
200
|
+
};
|
|
201
|
+
}, [renderer, camera, config.resolution]);
|
|
202
|
+
useEffect(() => {
|
|
203
|
+
if (!ssrMaterial.current) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const u = ssrMaterial.current.uniforms;
|
|
207
|
+
u.maxSteps.value = config.maxSteps;
|
|
208
|
+
u.maxDistance.value = config.maxDistance;
|
|
209
|
+
u.thickness.value = config.thickness;
|
|
210
|
+
u.jitter.value = config.jitter;
|
|
211
|
+
u.intensity.value = config.intensity;
|
|
212
|
+
u.fresnelExponent.value = config.fresnelExponent;
|
|
213
|
+
}, [config]);
|
|
214
|
+
const update = useCallback(() => {
|
|
215
|
+
if (!renderer || !scene || !camera || !config.enabled) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (!renderTarget || !depthTarget.current) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
renderer.setRenderTarget(depthTarget.current);
|
|
222
|
+
renderer.render(scene, camera);
|
|
223
|
+
renderer.setRenderTarget(renderTarget);
|
|
224
|
+
renderer.render(scene, camera);
|
|
225
|
+
if (ssrMaterial.current) {
|
|
226
|
+
ssrMaterial.current.uniforms.projMatrix.value.copy(camera.projectionMatrix);
|
|
227
|
+
ssrMaterial.current.uniforms.projInverseMatrix.value.copy(camera.projectionMatrixInverse);
|
|
228
|
+
ssrMaterial.current.uniforms.viewMatrix.value.copy(camera.matrixWorldInverse);
|
|
229
|
+
}
|
|
230
|
+
renderer.setRenderTarget(null);
|
|
231
|
+
renderer.render(orthoScene.current, orthoCamera.current);
|
|
232
|
+
}, [renderer, scene, camera, config.enabled, renderTarget]);
|
|
233
|
+
const dispose = useCallback(() => {
|
|
234
|
+
renderTarget?.dispose();
|
|
235
|
+
depthTarget.current?.dispose();
|
|
236
|
+
normalTarget.current?.dispose();
|
|
237
|
+
ssrMaterial.current?.dispose();
|
|
238
|
+
}, [renderTarget]);
|
|
239
|
+
return { config, setConfig, renderTarget, update, dispose };
|
|
240
|
+
}
|
|
241
|
+
const NiceSSR = ({
|
|
242
|
+
renderer,
|
|
243
|
+
scene,
|
|
244
|
+
camera,
|
|
245
|
+
config: configProp,
|
|
246
|
+
className = ""
|
|
247
|
+
}) => {
|
|
248
|
+
const { t } = useNiceTranslation();
|
|
249
|
+
const { config, setConfig } = useSSR(renderer, scene, camera, configProp);
|
|
250
|
+
return /* @__PURE__ */ jsxs("div", { className: `nice-ssr ${className}`, style: { display: "grid", gap: 8, fontSize: 13 }, children: [
|
|
251
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
|
|
252
|
+
/* @__PURE__ */ jsxs("strong", { children: [
|
|
253
|
+
/* @__PURE__ */ jsx(NiceIcon, { name: "copy", size: 14 }),
|
|
254
|
+
" ",
|
|
255
|
+
t("ssr.screenSpaceReflections", "Screen-Space Reflections")
|
|
256
|
+
] }),
|
|
257
|
+
/* @__PURE__ */ jsxs("label", { style: { display: "flex", alignItems: "center", gap: 4, fontSize: 11 }, children: [
|
|
258
|
+
/* @__PURE__ */ jsx(
|
|
259
|
+
"input",
|
|
260
|
+
{
|
|
261
|
+
type: "checkbox",
|
|
262
|
+
checked: config.enabled,
|
|
263
|
+
onChange: (e) => setConfig({ enabled: e.target.checked })
|
|
264
|
+
}
|
|
265
|
+
),
|
|
266
|
+
t("ssr.enabled", "Enabled")
|
|
267
|
+
] })
|
|
268
|
+
] }),
|
|
269
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
270
|
+
t("ssr.maxSteps", "Max Steps: {maxSteps}").replace("{maxSteps}", String(config.maxSteps)),
|
|
271
|
+
/* @__PURE__ */ jsx(
|
|
272
|
+
"input",
|
|
273
|
+
{
|
|
274
|
+
type: "range",
|
|
275
|
+
min: 16,
|
|
276
|
+
max: 256,
|
|
277
|
+
step: 16,
|
|
278
|
+
value: config.maxSteps,
|
|
279
|
+
onChange: (e) => setConfig({ maxSteps: parseInt(e.target.value, 10) }),
|
|
280
|
+
style: { width: "100%" }
|
|
146
281
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
dTarget.depthTexture = new THREE.DepthTexture(width, height);
|
|
165
|
-
dTarget.depthTexture.type = THREE.UnsignedIntType;
|
|
166
|
-
depthTarget.current = dTarget;
|
|
167
|
-
// Normal render target
|
|
168
|
-
const nTarget = new THREE.WebGLRenderTarget(width, height, {
|
|
169
|
-
minFilter: THREE.NearestFilter,
|
|
170
|
-
magFilter: THREE.NearestFilter,
|
|
171
|
-
format: THREE.RGBAFormat,
|
|
172
|
-
});
|
|
173
|
-
normalTarget.current = nTarget;
|
|
174
|
-
// SSR shader material
|
|
175
|
-
const material = new THREE.ShaderMaterial({
|
|
176
|
-
vertexShader: SSR_VERTEX,
|
|
177
|
-
fragmentShader: SSR_FRAGMENT,
|
|
178
|
-
uniforms: {
|
|
179
|
-
tDiffuse: { value: sceneRT.texture },
|
|
180
|
-
tDepth: { value: dTarget.depthTexture },
|
|
181
|
-
tNormal: { value: nTarget.texture },
|
|
182
|
-
projMatrix: { value: camera.projectionMatrix },
|
|
183
|
-
projInverseMatrix: { value: camera.projectionMatrixInverse },
|
|
184
|
-
viewMatrix: { value: camera.matrixWorldInverse },
|
|
185
|
-
resolution: { value: new THREE.Vector2(width, height) },
|
|
186
|
-
cameraNear: { value: camera.near },
|
|
187
|
-
cameraFar: { value: camera.far },
|
|
188
|
-
maxSteps: { value: config.maxSteps },
|
|
189
|
-
maxDistance: { value: config.maxDistance },
|
|
190
|
-
thickness: { value: config.thickness },
|
|
191
|
-
jitter: { value: config.jitter },
|
|
192
|
-
intensity: { value: config.intensity },
|
|
193
|
-
fresnelExponent: { value: config.fresnelExponent },
|
|
194
|
-
},
|
|
195
|
-
});
|
|
196
|
-
ssrMaterial.current = material;
|
|
197
|
-
// Full-screen quad
|
|
198
|
-
const quad = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), material);
|
|
199
|
-
quad.frustumCulled = false;
|
|
200
|
-
const ortho = orthoScene.current;
|
|
201
|
-
ortho.add(quad);
|
|
202
|
-
fullScreenQuad.current = quad;
|
|
203
|
-
return () => {
|
|
204
|
-
sceneRT.dispose();
|
|
205
|
-
dTarget.dispose();
|
|
206
|
-
nTarget.dispose();
|
|
207
|
-
material.dispose();
|
|
208
|
-
ortho.remove(quad);
|
|
209
|
-
};
|
|
210
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps -- the uniforms' first values; the next effect updates them without rebuilding the render targets
|
|
211
|
-
}, [renderer, camera, config.resolution]);
|
|
212
|
-
// Update uniforms when config changes
|
|
213
|
-
useEffect(() => {
|
|
214
|
-
if (!ssrMaterial.current) {
|
|
215
|
-
return;
|
|
282
|
+
)
|
|
283
|
+
] }),
|
|
284
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
285
|
+
t("ssr.maxDistance", "Max Distance: {maxDistance}").replace(
|
|
286
|
+
"{maxDistance}",
|
|
287
|
+
String(config.maxDistance)
|
|
288
|
+
),
|
|
289
|
+
/* @__PURE__ */ jsx(
|
|
290
|
+
"input",
|
|
291
|
+
{
|
|
292
|
+
type: "range",
|
|
293
|
+
min: 5,
|
|
294
|
+
max: 200,
|
|
295
|
+
step: 5,
|
|
296
|
+
value: config.maxDistance,
|
|
297
|
+
onChange: (e) => setConfig({ maxDistance: parseInt(e.target.value, 10) }),
|
|
298
|
+
style: { width: "100%" }
|
|
216
299
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
300
|
+
)
|
|
301
|
+
] }),
|
|
302
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
303
|
+
t("ssr.intensity", "Intensity: {intensity}").replace(
|
|
304
|
+
"{intensity}",
|
|
305
|
+
String(config.intensity.toFixed(2))
|
|
306
|
+
),
|
|
307
|
+
/* @__PURE__ */ jsx(
|
|
308
|
+
"input",
|
|
309
|
+
{
|
|
310
|
+
type: "range",
|
|
311
|
+
min: 0,
|
|
312
|
+
max: 1,
|
|
313
|
+
step: 0.05,
|
|
314
|
+
value: config.intensity,
|
|
315
|
+
onChange: (e) => setConfig({ intensity: parseFloat(e.target.value) }),
|
|
316
|
+
style: { width: "100%" }
|
|
228
317
|
}
|
|
229
|
-
|
|
230
|
-
|
|
318
|
+
)
|
|
319
|
+
] }),
|
|
320
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
321
|
+
t("ssr.thickness", "Thickness: {thickness}").replace(
|
|
322
|
+
"{thickness}",
|
|
323
|
+
String(config.thickness.toFixed(2))
|
|
324
|
+
),
|
|
325
|
+
/* @__PURE__ */ jsx(
|
|
326
|
+
"input",
|
|
327
|
+
{
|
|
328
|
+
type: "range",
|
|
329
|
+
min: 0.05,
|
|
330
|
+
max: 2,
|
|
331
|
+
step: 0.05,
|
|
332
|
+
value: config.thickness,
|
|
333
|
+
onChange: (e) => setConfig({ thickness: parseFloat(e.target.value) }),
|
|
334
|
+
style: { width: "100%" }
|
|
231
335
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
336
|
+
)
|
|
337
|
+
] }),
|
|
338
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
339
|
+
t("ssr.jitter", "Jitter: {jitter}").replace("{jitter}", String(config.jitter.toFixed(2))),
|
|
340
|
+
/* @__PURE__ */ jsx(
|
|
341
|
+
"input",
|
|
342
|
+
{
|
|
343
|
+
type: "range",
|
|
344
|
+
min: 0,
|
|
345
|
+
max: 1,
|
|
346
|
+
step: 0.05,
|
|
347
|
+
value: config.jitter,
|
|
348
|
+
onChange: (e) => setConfig({ jitter: parseFloat(e.target.value) }),
|
|
349
|
+
style: { width: "100%" }
|
|
242
350
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
351
|
+
)
|
|
352
|
+
] }),
|
|
353
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
354
|
+
t("ssr.resolutionScale", "Resolution Scale: {resolution}").replace(
|
|
355
|
+
"{resolution}",
|
|
356
|
+
String(config.resolution.toFixed(2))
|
|
357
|
+
),
|
|
358
|
+
/* @__PURE__ */ jsx(
|
|
359
|
+
"input",
|
|
360
|
+
{
|
|
361
|
+
type: "range",
|
|
362
|
+
min: 0.25,
|
|
363
|
+
max: 1,
|
|
364
|
+
step: 0.25,
|
|
365
|
+
value: config.resolution,
|
|
366
|
+
onChange: (e) => setConfig({ resolution: parseFloat(e.target.value) }),
|
|
367
|
+
style: { width: "100%" }
|
|
368
|
+
}
|
|
369
|
+
)
|
|
370
|
+
] }),
|
|
371
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
372
|
+
t("ssr.fresnel", "Fresnel: {fresnelExponent}").replace(
|
|
373
|
+
"{fresnelExponent}",
|
|
374
|
+
String(config.fresnelExponent.toFixed(1))
|
|
375
|
+
),
|
|
376
|
+
/* @__PURE__ */ jsx(
|
|
377
|
+
"input",
|
|
378
|
+
{
|
|
379
|
+
type: "range",
|
|
380
|
+
min: 1,
|
|
381
|
+
max: 8,
|
|
382
|
+
step: 0.5,
|
|
383
|
+
value: config.fresnelExponent,
|
|
384
|
+
onChange: (e) => setConfig({ fresnelExponent: parseFloat(e.target.value) }),
|
|
385
|
+
style: { width: "100%" }
|
|
386
|
+
}
|
|
387
|
+
)
|
|
388
|
+
] })
|
|
389
|
+
] });
|
|
390
|
+
};
|
|
391
|
+
export {
|
|
392
|
+
NiceSSR,
|
|
393
|
+
useSSR
|
|
261
394
|
};
|
|
262
|
-
|
|
263
|
-
export { NiceSSR, useSSR };
|