three-base 2.0.19 → 2.0.20

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/Mirror.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ import { BufferGeometry, Camera, Group, Material, Matrix4, Mesh, PerspectiveCamera, Plane, PlaneGeometry, Scene, ShaderMaterial, Vector3, Vector4, WebGLRenderTarget, WebGLRenderer } from "three";
2
+ export default class Mirror extends Mesh {
3
+ constructor(geometry?: BufferGeometry);
4
+ static geometry: PlaneGeometry;
5
+ isReflector: boolean;
6
+ type: string;
7
+ camera: PerspectiveCamera;
8
+ reflectorPlane: Plane;
9
+ normal: Vector3;
10
+ reflectorWorldPosition: Vector3;
11
+ cameraWorldPosition: Vector3;
12
+ rotationMatrix: Matrix4;
13
+ lookAtPosition: Vector3;
14
+ clipPlane: Vector4;
15
+ view: Vector3;
16
+ target: Vector3;
17
+ q: Vector4;
18
+ textureMatrix: Matrix4;
19
+ virtualCamera: PerspectiveCamera;
20
+ renderTarget: WebGLRenderTarget<import("three").Texture>;
21
+ material: ShaderMaterial;
22
+ onBeforeRender: (renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, material: Material, group: Group) => void;
23
+ getRenderTarget(): WebGLRenderTarget<import("three").Texture>;
24
+ dispose(): void;
25
+ }
package/Mirror.js ADDED
@@ -0,0 +1,197 @@
1
+ /*
2
+ * @Author: xiaosihan
3
+ * @Date: 2023-08-04 17:17:15
4
+ * @Last Modified by: xiaosihan
5
+ * @Last Modified time: 2023-08-04 20:54:29
6
+ */
7
+ import { Color, DoubleSide, HalfFloatType, Matrix4, Mesh, PerspectiveCamera, Plane, PlaneGeometry, ShaderMaterial, Vector3, Vector4, WebGLRenderTarget } from "three";
8
+ // 镜子模型
9
+ export default class Mirror extends Mesh {
10
+ constructor(geometry = Mirror.geometry) {
11
+ super(geometry);
12
+ }
13
+ // 正方形网格
14
+ static geometry = (() => {
15
+ const geometry = new PlaneGeometry(10, 10, 1, 1);
16
+ return geometry;
17
+ })();
18
+ isReflector = true;
19
+ type = 'Reflector';
20
+ camera = new PerspectiveCamera();
21
+ reflectorPlane = new Plane();
22
+ normal = new Vector3();
23
+ reflectorWorldPosition = new Vector3();
24
+ cameraWorldPosition = new Vector3();
25
+ rotationMatrix = new Matrix4();
26
+ lookAtPosition = new Vector3(0, 0, -1);
27
+ clipPlane = new Vector4();
28
+ view = new Vector3();
29
+ target = new Vector3();
30
+ q = new Vector4();
31
+ textureMatrix = new Matrix4();
32
+ virtualCamera = this.camera;
33
+ renderTarget = new WebGLRenderTarget(2048, 2048, { samples: 0, type: HalfFloatType });
34
+ material = new ShaderMaterial({
35
+ uniforms: {
36
+ 'color': {
37
+ value: new Color("#b6b6b6")
38
+ },
39
+ 'tDiffuse': {
40
+ value: this.renderTarget.texture
41
+ },
42
+ 'textureMatrix': {
43
+ value: this.textureMatrix
44
+ },
45
+ blurAmount: {
46
+ value: 0.5
47
+ } // 模糊程度,可以根据需求调整
48
+ },
49
+ vertexShader: /* glsl */ `
50
+ uniform mat4 textureMatrix;
51
+ varying vec4 vUv;
52
+
53
+ #include <common>
54
+ #include <logdepthbuf_pars_vertex>
55
+
56
+ void main() {
57
+
58
+ vUv = textureMatrix * vec4( position, 1.0 );
59
+
60
+ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
61
+
62
+ #include <logdepthbuf_vertex>
63
+
64
+ }`,
65
+ fragmentShader: /* glsl */ `
66
+ uniform vec3 color;
67
+ uniform sampler2D tDiffuse;
68
+ varying vec4 vUv;
69
+ uniform float blurAmount;
70
+
71
+ #include <logdepthbuf_pars_fragment>
72
+
73
+ float blendOverlay( float base, float blend ) {
74
+
75
+ return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );
76
+
77
+ }
78
+
79
+ vec3 blendOverlay( vec3 base, vec3 blend ) {
80
+
81
+ return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) );
82
+
83
+ }
84
+
85
+ void main() {
86
+
87
+ #include <logdepthbuf_fragment>
88
+
89
+ vec2 texelSize = 1.0 / vec2(1024,1024);
90
+ vec4 fragColor = vec4(0.0);
91
+
92
+ for (float offsetX = -blurAmount; offsetX <= blurAmount; offsetX += texelSize.x) {
93
+ for (float offsetY = -blurAmount; offsetY <= blurAmount; offsetY += texelSize.y) {
94
+ // fragColor += texture2DProj(tDiffuse, vUv + vec4(offsetX, offsetY, 0.0, 0.0) * texelSize);
95
+ fragColor += texture2DProj(tDiffuse, vUv + vec4(offsetX * texelSize.x, offsetY * texelSize.y, 0.0, 0.0) );
96
+ }
97
+ }
98
+
99
+ // fragColor /= pow(2.0 * blurAmount + 1.0, 2.0);
100
+ // gl_FragColor = color;
101
+
102
+ fragColor = texture2DProj( tDiffuse, vUv );
103
+ gl_FragColor = vec4( blendOverlay( fragColor.rgb, color ), 1.0 );
104
+
105
+ #include <tonemapping_fragment>
106
+ #include <colorspace_fragment>
107
+ }`,
108
+ depthTest: true,
109
+ depthWrite: true,
110
+ transparent: true,
111
+ side: DoubleSide
112
+ });
113
+ onBeforeRender = (renderer, scene, camera, geometry, material, group) => {
114
+ this.reflectorWorldPosition.setFromMatrixPosition(this.matrixWorld);
115
+ this.cameraWorldPosition.setFromMatrixPosition(camera.matrixWorld);
116
+ this.rotationMatrix.extractRotation(this.matrixWorld);
117
+ this.normal.set(0, 0, 1);
118
+ this.normal.applyMatrix4(this.rotationMatrix);
119
+ this.view.subVectors(this.reflectorWorldPosition, this.cameraWorldPosition);
120
+ // Avoid rendering when reflector is facing away
121
+ if (this.view.dot(this.normal) > 0) {
122
+ this.normal.set(0, 0, -1);
123
+ }
124
+ ;
125
+ this.view.reflect(this.normal).negate();
126
+ this.view.add(this.reflectorWorldPosition);
127
+ this.rotationMatrix.extractRotation(camera.matrixWorld);
128
+ this.lookAtPosition.set(0, 0, -1);
129
+ this.lookAtPosition.applyMatrix4(this.rotationMatrix);
130
+ this.lookAtPosition.add(this.cameraWorldPosition);
131
+ this.target.subVectors(this.reflectorWorldPosition, this.lookAtPosition);
132
+ this.target.reflect(this.normal).negate();
133
+ this.target.add(this.reflectorWorldPosition);
134
+ this.virtualCamera.position.copy(this.view);
135
+ this.virtualCamera.up.set(0, 1, 0);
136
+ this.virtualCamera.up.applyMatrix4(this.rotationMatrix);
137
+ this.virtualCamera.up.reflect(this.normal);
138
+ this.virtualCamera.lookAt(this.target);
139
+ this.virtualCamera.far = this.camera.far; // Used in WebGLBackground
140
+ this.virtualCamera.updateMatrixWorld();
141
+ this.virtualCamera.projectionMatrix.copy(camera.projectionMatrix);
142
+ // Update the texture matrix
143
+ this.textureMatrix.set(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0);
144
+ this.textureMatrix.multiply(this.virtualCamera.projectionMatrix);
145
+ this.textureMatrix.multiply(this.virtualCamera.matrixWorldInverse);
146
+ this.textureMatrix.multiply(this.matrixWorld);
147
+ // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
148
+ // Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
149
+ this.reflectorPlane.setFromNormalAndCoplanarPoint(this.normal, this.reflectorWorldPosition);
150
+ this.reflectorPlane.applyMatrix4(this.virtualCamera.matrixWorldInverse);
151
+ this.clipPlane.set(this.reflectorPlane.normal.x, this.reflectorPlane.normal.y, this.reflectorPlane.normal.z, this.reflectorPlane.constant);
152
+ const projectionMatrix = this.virtualCamera.projectionMatrix;
153
+ this.q.x = (Math.sign(this.clipPlane.x) + projectionMatrix.elements[8]) / projectionMatrix.elements[0];
154
+ this.q.y = (Math.sign(this.clipPlane.y) + projectionMatrix.elements[9]) / projectionMatrix.elements[5];
155
+ this.q.z = -1.0;
156
+ this.q.w = (1.0 + projectionMatrix.elements[10]) / projectionMatrix.elements[14];
157
+ // Calculate the scaled plane vector
158
+ this.clipPlane.multiplyScalar(2.0 / this.clipPlane.dot(this.q));
159
+ // Replacing the third row of the projection matrix
160
+ projectionMatrix.elements[2] = this.clipPlane.x;
161
+ projectionMatrix.elements[6] = this.clipPlane.y;
162
+ projectionMatrix.elements[10] = this.clipPlane.z + 1.0 - 0.003;
163
+ projectionMatrix.elements[14] = this.clipPlane.w;
164
+ // Render
165
+ this.visible = false;
166
+ const currentRenderTarget = renderer.getRenderTarget();
167
+ const currentXrEnabled = renderer.xr.enabled;
168
+ const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
169
+ renderer.xr.enabled = false; // Avoid camera modification
170
+ renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
171
+ renderer.setRenderTarget(this.renderTarget);
172
+ renderer.state.buffers.depth.setMask(true); // make sure the depth buffer is writable so it can be properly cleared, see #18897
173
+ if (renderer.autoClear === false)
174
+ renderer.clear();
175
+ renderer.render(scene, this.virtualCamera);
176
+ renderer.xr.enabled = currentXrEnabled;
177
+ renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
178
+ renderer.setRenderTarget(currentRenderTarget);
179
+ // Restore viewport
180
+ //@ts-ignore
181
+ const viewport = this.camera.viewport;
182
+ if (viewport !== undefined) {
183
+ debugger;
184
+ renderer.state.viewport(viewport);
185
+ }
186
+ this.visible = true;
187
+ };
188
+ getRenderTarget() {
189
+ return this.renderTarget;
190
+ }
191
+ ;
192
+ dispose() {
193
+ this.renderTarget.dispose();
194
+ // this.material.dispose();
195
+ }
196
+ ;
197
+ }
package/Mirror.ts ADDED
@@ -0,0 +1,255 @@
1
+ /*
2
+ * @Author: xiaosihan
3
+ * @Date: 2023-08-04 17:17:15
4
+ * @Last Modified by: xiaosihan
5
+ * @Last Modified time: 2023-08-04 20:54:29
6
+ */
7
+
8
+ import { BufferGeometry, Camera, Color, DoubleSide, Group, HalfFloatType, Material, Matrix4, Mesh, PerspectiveCamera, Plane, PlaneGeometry, Scene, ShaderMaterial, Vector3, Vector4, WebGLRenderTarget, WebGLRenderer } from "three";
9
+
10
+
11
+ // 镜子模型
12
+ export default class Mirror extends Mesh {
13
+
14
+ constructor(geometry: BufferGeometry = Mirror.geometry) {
15
+ super(geometry);
16
+ }
17
+
18
+ // 正方形网格
19
+ static geometry = (() => {
20
+ const geometry = new PlaneGeometry(10, 10, 1, 1);
21
+ return geometry;
22
+ })();
23
+
24
+ isReflector = true;
25
+
26
+ type = 'Reflector';
27
+
28
+ camera = new PerspectiveCamera();
29
+
30
+ reflectorPlane = new Plane();
31
+ normal = new Vector3();
32
+ reflectorWorldPosition = new Vector3();
33
+ cameraWorldPosition = new Vector3();
34
+ rotationMatrix = new Matrix4();
35
+ lookAtPosition = new Vector3(0, 0, - 1);
36
+ clipPlane = new Vector4();
37
+
38
+ view = new Vector3();
39
+ target = new Vector3();
40
+ q = new Vector4();
41
+
42
+ textureMatrix = new Matrix4();
43
+ virtualCamera = this.camera;
44
+
45
+ renderTarget = new WebGLRenderTarget(2048, 2048, { samples: 0, type: HalfFloatType });
46
+
47
+ material = new ShaderMaterial({
48
+ uniforms: {
49
+ 'color': {
50
+ value: new Color("#b6b6b6")
51
+ },
52
+
53
+ 'tDiffuse': {
54
+ value: this.renderTarget.texture
55
+ },
56
+
57
+ 'textureMatrix': {
58
+ value: this.textureMatrix
59
+ },
60
+ blurAmount: {
61
+ value: 0.5
62
+ } // 模糊程度,可以根据需求调整
63
+
64
+ },
65
+
66
+ vertexShader: /* glsl */`
67
+ uniform mat4 textureMatrix;
68
+ varying vec4 vUv;
69
+
70
+ #include <common>
71
+ #include <logdepthbuf_pars_vertex>
72
+
73
+ void main() {
74
+
75
+ vUv = textureMatrix * vec4( position, 1.0 );
76
+
77
+ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
78
+
79
+ #include <logdepthbuf_vertex>
80
+
81
+ }`,
82
+
83
+ fragmentShader: /* glsl */`
84
+ uniform vec3 color;
85
+ uniform sampler2D tDiffuse;
86
+ varying vec4 vUv;
87
+ uniform float blurAmount;
88
+
89
+ #include <logdepthbuf_pars_fragment>
90
+
91
+ float blendOverlay( float base, float blend ) {
92
+
93
+ return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );
94
+
95
+ }
96
+
97
+ vec3 blendOverlay( vec3 base, vec3 blend ) {
98
+
99
+ return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) );
100
+
101
+ }
102
+
103
+ void main() {
104
+
105
+ #include <logdepthbuf_fragment>
106
+
107
+ vec2 texelSize = 1.0 / vec2(1024,1024);
108
+ vec4 fragColor = vec4(0.0);
109
+
110
+ for (float offsetX = -blurAmount; offsetX <= blurAmount; offsetX += texelSize.x) {
111
+ for (float offsetY = -blurAmount; offsetY <= blurAmount; offsetY += texelSize.y) {
112
+ // fragColor += texture2DProj(tDiffuse, vUv + vec4(offsetX, offsetY, 0.0, 0.0) * texelSize);
113
+ fragColor += texture2DProj(tDiffuse, vUv + vec4(offsetX * texelSize.x, offsetY * texelSize.y, 0.0, 0.0) );
114
+ }
115
+ }
116
+
117
+ // fragColor /= pow(2.0 * blurAmount + 1.0, 2.0);
118
+ // gl_FragColor = color;
119
+
120
+ fragColor = texture2DProj( tDiffuse, vUv );
121
+ gl_FragColor = vec4( blendOverlay( fragColor.rgb, color ), 1.0 );
122
+
123
+ #include <tonemapping_fragment>
124
+ #include <colorspace_fragment>
125
+ }`,
126
+ depthTest: true,
127
+ depthWrite: true,
128
+ transparent: true,
129
+ side: DoubleSide
130
+ });
131
+
132
+
133
+ onBeforeRender = (renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, material: Material, group: Group) => {
134
+
135
+ this.reflectorWorldPosition.setFromMatrixPosition(this.matrixWorld);
136
+ this.cameraWorldPosition.setFromMatrixPosition(camera.matrixWorld);
137
+
138
+ this.rotationMatrix.extractRotation(this.matrixWorld);
139
+
140
+ this.normal.set(0, 0, 1);
141
+ this.normal.applyMatrix4(this.rotationMatrix);
142
+
143
+ this.view.subVectors(this.reflectorWorldPosition, this.cameraWorldPosition);
144
+
145
+ // Avoid rendering when reflector is facing away
146
+
147
+ if (this.view.dot(this.normal) > 0) {
148
+ this.normal.set(0, 0, -1);
149
+ };
150
+
151
+ this.view.reflect(this.normal).negate();
152
+ this.view.add(this.reflectorWorldPosition);
153
+
154
+ this.rotationMatrix.extractRotation(camera.matrixWorld);
155
+
156
+ this.lookAtPosition.set(0, 0, - 1);
157
+ this.lookAtPosition.applyMatrix4(this.rotationMatrix);
158
+ this.lookAtPosition.add(this.cameraWorldPosition);
159
+
160
+ this.target.subVectors(this.reflectorWorldPosition, this.lookAtPosition);
161
+ this.target.reflect(this.normal).negate();
162
+ this.target.add(this.reflectorWorldPosition);
163
+
164
+ this.virtualCamera.position.copy(this.view);
165
+ this.virtualCamera.up.set(0, 1, 0);
166
+ this.virtualCamera.up.applyMatrix4(this.rotationMatrix);
167
+ this.virtualCamera.up.reflect(this.normal);
168
+ this.virtualCamera.lookAt(this.target);
169
+
170
+ this.virtualCamera.far = this.camera.far; // Used in WebGLBackground
171
+
172
+ this.virtualCamera.updateMatrixWorld();
173
+ this.virtualCamera.projectionMatrix.copy(camera.projectionMatrix);
174
+
175
+ // Update the texture matrix
176
+ this.textureMatrix.set(
177
+ 0.5, 0.0, 0.0, 0.5,
178
+ 0.0, 0.5, 0.0, 0.5,
179
+ 0.0, 0.0, 0.5, 0.5,
180
+ 0.0, 0.0, 0.0, 1.0
181
+ );
182
+ this.textureMatrix.multiply(this.virtualCamera.projectionMatrix);
183
+ this.textureMatrix.multiply(this.virtualCamera.matrixWorldInverse);
184
+ this.textureMatrix.multiply(this.matrixWorld);
185
+
186
+ // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
187
+ // Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
188
+ this.reflectorPlane.setFromNormalAndCoplanarPoint(this.normal, this.reflectorWorldPosition);
189
+ this.reflectorPlane.applyMatrix4(this.virtualCamera.matrixWorldInverse);
190
+
191
+ this.clipPlane.set(this.reflectorPlane.normal.x, this.reflectorPlane.normal.y, this.reflectorPlane.normal.z, this.reflectorPlane.constant);
192
+
193
+ const projectionMatrix = this.virtualCamera.projectionMatrix;
194
+
195
+ this.q.x = (Math.sign(this.clipPlane.x) + projectionMatrix.elements[8]) / projectionMatrix.elements[0];
196
+ this.q.y = (Math.sign(this.clipPlane.y) + projectionMatrix.elements[9]) / projectionMatrix.elements[5];
197
+ this.q.z = - 1.0;
198
+ this.q.w = (1.0 + projectionMatrix.elements[10]) / projectionMatrix.elements[14];
199
+
200
+ // Calculate the scaled plane vector
201
+ this.clipPlane.multiplyScalar(2.0 / this.clipPlane.dot(this.q));
202
+
203
+ // Replacing the third row of the projection matrix
204
+ projectionMatrix.elements[2] = this.clipPlane.x;
205
+ projectionMatrix.elements[6] = this.clipPlane.y;
206
+ projectionMatrix.elements[10] = this.clipPlane.z + 1.0 - 0.003;
207
+ projectionMatrix.elements[14] = this.clipPlane.w;
208
+
209
+ // Render
210
+ this.visible = false;
211
+
212
+ const currentRenderTarget = renderer.getRenderTarget();
213
+
214
+ const currentXrEnabled = renderer.xr.enabled;
215
+ const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
216
+
217
+ renderer.xr.enabled = false; // Avoid camera modification
218
+ renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
219
+
220
+ renderer.setRenderTarget(this.renderTarget);
221
+
222
+ renderer.state.buffers.depth.setMask(true); // make sure the depth buffer is writable so it can be properly cleared, see #18897
223
+
224
+ if (renderer.autoClear === false) renderer.clear();
225
+ renderer.render(scene, this.virtualCamera);
226
+
227
+ renderer.xr.enabled = currentXrEnabled;
228
+ renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
229
+
230
+ renderer.setRenderTarget(currentRenderTarget);
231
+
232
+ // Restore viewport
233
+ //@ts-ignore
234
+ const viewport = this.camera.viewport;
235
+ if (viewport !== undefined) {
236
+ debugger;
237
+ renderer.state.viewport(viewport);
238
+ }
239
+
240
+ this.visible = true;
241
+
242
+ }
243
+
244
+ getRenderTarget() {
245
+
246
+ return this.renderTarget;
247
+
248
+ };
249
+
250
+ dispose() {
251
+ this.renderTarget.dispose();
252
+ // this.material.dispose();
253
+ };
254
+
255
+ }
package/ThreeBase.d.ts CHANGED
@@ -16,7 +16,6 @@ export default class ThreeBase extends EventDispatcher {
16
16
  scene: Scene;
17
17
  threeMouse: ThreeMouse;
18
18
  controls: OrbitControls;
19
- isRendererContextLost: boolean;
20
19
  setContainer(div: HTMLDivElement | null): Promise<void>;
21
20
  setSize(width: number, height: number): void;
22
21
  controlsDistance: Transition;
package/ThreeBase.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * @Last Modified time: 2023-05-23 23:54:13
6
6
  */
7
7
  import { round } from "lodash";
8
- import { AxesHelper, DepthFormat, DepthTexture, DisplayP3ColorSpace, EventDispatcher, GridHelper, LinearFilter, Mesh, MOUSE, NoBlending, NormalBlending, PerspectiveCamera, RGBAFormat, Scene, TOUCH, UnsignedShortType, Vector2, Vector3, WebGLRenderer, WebGLRenderTarget } from "three";
8
+ import { AxesHelper, DepthFormat, DepthTexture, EventDispatcher, GridHelper, LinearFilter, Mesh, MOUSE, NoBlending, NormalBlending, PerspectiveCamera, RGBAFormat, Scene, TOUCH, UnsignedShortType, Vector2, Vector3, WebGLRenderer, WebGLRenderTarget } from "three";
9
9
  import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
10
10
  import { generateUUID } from "three/src/math/MathUtils";
11
11
  import { clearShader, coptyShader, fullScreenMesh, gaussBlurShader, strokeShader } from "./shaders";
@@ -31,19 +31,17 @@ export default class ThreeBase extends EventDispatcher {
31
31
  })();
32
32
  // TODO 渲染目标的颜色空间问题 还没有处理好
33
33
  // 基础纹理渲染对象
34
- baseRenderTarget = new WebGLRenderTarget(128, 128, {
35
- minFilter: LinearFilter,
36
- magFilter: LinearFilter,
37
- format: RGBAFormat,
38
- stencilBuffer: false,
39
- depthTexture: this.baseDepthTexture,
40
- anisotropy: 16,
41
- colorSpace: DisplayP3ColorSpace
42
- // | typeof NoColorSpace
43
- // | typeof SRGBColorSpace
44
- // | typeof LinearSRGBColorSpace
45
- // | typeof DisplayP3ColorSpace;
46
- });
34
+ baseRenderTarget = (() => {
35
+ const baseRenderTarget = new WebGLRenderTarget(128, 128, {
36
+ minFilter: LinearFilter,
37
+ magFilter: LinearFilter,
38
+ format: RGBAFormat,
39
+ stencilBuffer: false,
40
+ depthTexture: this.baseDepthTexture,
41
+ anisotropy: 16,
42
+ });
43
+ return baseRenderTarget;
44
+ })();
47
45
  // 公用渲染目标1
48
46
  renderTarget = new WebGLRenderTarget(128, 128, { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat });
49
47
  // 渲染目标2
@@ -91,22 +89,17 @@ export default class ThreeBase extends EventDispatcher {
91
89
  controls.screenSpacePanning = true;
92
90
  return controls;
93
91
  })();
94
- // 上下文是否被销毁了
95
- isRendererContextLost = false;
96
92
  // 设置 dom 容器
97
93
  async setContainer(div) {
98
94
  if (div) {
99
95
  div.style.overflow = "hidden";
100
96
  div.innerHTML = "";
101
97
  div.append(this.renderer.domElement);
102
- // 如果上下文被销毁了, 就恢复上下文
103
- if (this.isRendererContextLost) {
104
- this.isRendererContextLost = false;
105
- this.renderer.forceContextRestore();
106
- await new Promise(resolve => requestAnimationFrame(resolve));
107
- await new Promise(resolve => requestAnimationFrame(resolve));
108
- this.renderer.domElement.style.opacity = "1";
109
- }
98
+ // this.renderer.forceContextLoss();
99
+ // await new Promise(resolve => requestAnimationFrame(resolve));
100
+ // await new Promise(resolve => requestAnimationFrame(resolve));
101
+ this.renderer.forceContextRestore();
102
+ this.renderer.domElement.style.opacity = "1";
110
103
  this.setSize(div.clientWidth, div.clientHeight);
111
104
  // 开启时时渲染
112
105
  threeUtils.removeEventListener("requestAnimationFrame", this.renderBindThis);
@@ -121,7 +114,7 @@ export default class ThreeBase extends EventDispatcher {
121
114
  }
122
115
  this.renderer.setPixelRatio(window.devicePixelRatio);
123
116
  this.renderer.setSize(width, height);
124
- this.baseRenderTarget.setSize(width, height);
117
+ this.baseRenderTarget.setSize(width * window.devicePixelRatio, height * window.devicePixelRatio);
125
118
  this.size.set(width, height);
126
119
  // 渲染场景
127
120
  // this.renderer.clear();
@@ -149,11 +142,24 @@ export default class ThreeBase extends EventDispatcher {
149
142
  const controlsPosition = new Transition({ x: 100, y: 100, z: 100 });
150
143
  controlsPosition.setDuration(1000);
151
144
  controlsPosition.onChange(({ x, y, z }) => {
152
- // const distance = this.controlsDistance.get("distance");
153
- this.camera.position.set(x, y, z);
154
- // .sub(this.controls.target)
155
- // .setLength(distance)
156
- // .add(this.controls.target);
145
+ const distance = this.controlsDistance.get("distance");
146
+ this.camera.position.set(x + 0.01, y, z + 0.01)
147
+ .sub(this.controls.target)
148
+ .setLength(distance)
149
+ .add(this.controls.target);
150
+ // // 创建初始方向向量
151
+ // const directionVecA = new THREE.Vector3(1, 0, 0); // 需要旋转的初始方向向量
152
+ // const referenceVecB = new THREE.Vector3(0, 1, 0); // 参考方向向量,用于确定旋转轴
153
+ // // 归一化参考方向向量
154
+ // referenceVecB.normalize();
155
+ // // 计算旋转轴
156
+ // const axis = new THREE.Vector3().crossVectors(directionVecA, referenceVecB).normalize();
157
+ // // 计算旋转角度(弧度)
158
+ // const angle = Math.PI / 36; // 旋转角度为5度,Math.PI / 36为弧度
159
+ // // 使用applyAxisAngle方法进行旋转
160
+ // directionVecA.applyAxisAngle(axis, angle);
161
+ // // 输出旋转后的方向向量
162
+ // console.log(directionVecA);
157
163
  this.camera.lookAt(this.controls.target);
158
164
  this.needRender = true;
159
165
  });
@@ -162,15 +168,17 @@ export default class ThreeBase extends EventDispatcher {
162
168
  // 网格辅助线
163
169
  gridHelper = (() => {
164
170
  const gridHelper = new GridHelper(1000, 100, 0x303030, 0x303030);
165
- gridHelper.visible = threeUtils.isDev;
166
- this.scene.add(gridHelper);
171
+ if (threeUtils.isDev) {
172
+ this.scene.add(gridHelper);
173
+ }
167
174
  return gridHelper;
168
175
  })();
169
176
  //坐标轴线
170
177
  axesHelper = (() => {
171
178
  const axesHelper = new AxesHelper(10000);
172
- axesHelper.visible = threeUtils.isDev;
173
- this.scene.add(axesHelper);
179
+ if (threeUtils.isDev) {
180
+ this.scene.add(axesHelper);
181
+ }
174
182
  return axesHelper;
175
183
  })();
176
184
  init() {
@@ -266,8 +274,6 @@ export default class ThreeBase extends EventDispatcher {
266
274
  stopRender() {
267
275
  threeUtils.removeEventListener("requestAnimationFrame", this.renderBindThis);
268
276
  this.renderer.forceContextLoss();
269
- // 标记上下文被销毁了
270
- this.isRendererContextLost = true;
271
277
  this.setSize(100, 100);
272
278
  this.renderer.domElement.style.opacity = "0";
273
279
  }
@@ -297,17 +303,17 @@ export default class ThreeBase extends EventDispatcher {
297
303
  }
298
304
  // 渲染场景
299
305
  this.dispatchEvent({ type: "beforeRender" });
300
- this.renderer.setRenderTarget(this.baseRenderTarget);
306
+ // this.renderer.setRenderTarget(this.baseRenderTarget);
301
307
  this.renderer.clear();
302
308
  this.renderer.render(this.scene, this.camera);
303
- this.renderer.setRenderTarget(null);
304
- this.renderer.clear();
309
+ // this.renderer.setRenderTarget(null);
310
+ // this.renderer.clear();
305
311
  //TODO 渲染了2次, 还有优化空间
306
312
  // this.renderer.setScissorTest(false);
307
313
  // this.renderRendererTarget(this.baseRenderTarget);
308
314
  // this.renderer.setScissorTest(true);
309
- // this.renderer.setScissor(0, 0, 512, 1000);
310
- this.renderer.render(this.scene, this.camera);
315
+ // this.renderer.setScissor(0, 0, 800, 1000);
316
+ // this.renderer.render(this.scene, this.camera);
311
317
  // 查找需要绘制描边的对象,并且绘制描边
312
318
  this.scene.traverse(obj => {
313
319
  stroke_pass(this.renderer, this.camera, obj, this.baseDepthTexture);
package/ThreeBase.ts CHANGED
@@ -36,19 +36,17 @@ export default class ThreeBase extends EventDispatcher {
36
36
 
37
37
  // TODO 渲染目标的颜色空间问题 还没有处理好
38
38
  // 基础纹理渲染对象
39
- baseRenderTarget = new WebGLRenderTarget(128, 128, {
40
- minFilter: LinearFilter,
41
- magFilter: LinearFilter,
42
- format: RGBAFormat,
43
- stencilBuffer: false,
44
- depthTexture: this.baseDepthTexture,
45
- anisotropy: 16,
46
- colorSpace: DisplayP3ColorSpace
47
- // | typeof NoColorSpace
48
- // | typeof SRGBColorSpace
49
- // | typeof LinearSRGBColorSpace
50
- // | typeof DisplayP3ColorSpace;
51
- });
39
+ baseRenderTarget = (() => {
40
+ const baseRenderTarget = new WebGLRenderTarget(128, 128, {
41
+ minFilter: LinearFilter,
42
+ magFilter: LinearFilter,
43
+ format: RGBAFormat,
44
+ stencilBuffer: false,
45
+ depthTexture: this.baseDepthTexture,
46
+ anisotropy: 16,
47
+ });
48
+ return baseRenderTarget;
49
+ })();
52
50
 
53
51
  // 公用渲染目标1
54
52
  renderTarget = new WebGLRenderTarget(128, 128, { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat });
@@ -108,9 +106,6 @@ export default class ThreeBase extends EventDispatcher {
108
106
  return controls;
109
107
  })();
110
108
 
111
- // 上下文是否被销毁了
112
- isRendererContextLost = false;
113
-
114
109
  // 设置 dom 容器
115
110
  async setContainer(div: HTMLDivElement | null) {
116
111
  if (div) {
@@ -118,14 +113,11 @@ export default class ThreeBase extends EventDispatcher {
118
113
  div.innerHTML = "";
119
114
  div.append(this.renderer.domElement);
120
115
 
121
- // 如果上下文被销毁了, 就恢复上下文
122
- if (this.isRendererContextLost) {
123
- this.isRendererContextLost = false;
124
- this.renderer.forceContextRestore();
125
- await new Promise(resolve => requestAnimationFrame(resolve));
126
- await new Promise(resolve => requestAnimationFrame(resolve));
127
- this.renderer.domElement.style.opacity = "1";
128
- }
116
+ // this.renderer.forceContextLoss();
117
+ // await new Promise(resolve => requestAnimationFrame(resolve));
118
+ // await new Promise(resolve => requestAnimationFrame(resolve));
119
+ this.renderer.forceContextRestore();
120
+ this.renderer.domElement.style.opacity = "1";
129
121
 
130
122
  this.setSize(div.clientWidth, div.clientHeight);
131
123
 
@@ -145,7 +137,7 @@ export default class ThreeBase extends EventDispatcher {
145
137
  this.renderer.setPixelRatio(window.devicePixelRatio);
146
138
  this.renderer.setSize(width, height);
147
139
 
148
- this.baseRenderTarget.setSize(width, height);
140
+ this.baseRenderTarget.setSize(width * window.devicePixelRatio, height * window.devicePixelRatio);
149
141
 
150
142
  this.size.set(width, height);
151
143
  // 渲染场景
@@ -177,11 +169,31 @@ export default class ThreeBase extends EventDispatcher {
177
169
  const controlsPosition = new Transition({ x: 100, y: 100, z: 100 });
178
170
  controlsPosition.setDuration(1000);
179
171
  controlsPosition.onChange(({ x, y, z }) => {
180
- // const distance = this.controlsDistance.get("distance");
181
- this.camera.position.set(x, y, z)
182
- // .sub(this.controls.target)
183
- // .setLength(distance)
184
- // .add(this.controls.target);
172
+ const distance = this.controlsDistance.get("distance");
173
+ this.camera.position.set(x + 0.01, y, z + 0.01)
174
+ .sub(this.controls.target)
175
+ .setLength(distance)
176
+ .add(this.controls.target);
177
+
178
+ // // 创建初始方向向量
179
+ // const directionVecA = new THREE.Vector3(1, 0, 0); // 需要旋转的初始方向向量
180
+ // const referenceVecB = new THREE.Vector3(0, 1, 0); // 参考方向向量,用于确定旋转轴
181
+
182
+ // // 归一化参考方向向量
183
+ // referenceVecB.normalize();
184
+
185
+ // // 计算旋转轴
186
+ // const axis = new THREE.Vector3().crossVectors(directionVecA, referenceVecB).normalize();
187
+
188
+ // // 计算旋转角度(弧度)
189
+ // const angle = Math.PI / 36; // 旋转角度为5度,Math.PI / 36为弧度
190
+
191
+ // // 使用applyAxisAngle方法进行旋转
192
+ // directionVecA.applyAxisAngle(axis, angle);
193
+
194
+ // // 输出旋转后的方向向量
195
+ // console.log(directionVecA);
196
+
185
197
 
186
198
  this.camera.lookAt(this.controls.target);
187
199
  this.needRender = true;
@@ -192,16 +204,18 @@ export default class ThreeBase extends EventDispatcher {
192
204
  // 网格辅助线
193
205
  gridHelper = (() => {
194
206
  const gridHelper = new GridHelper(1000, 100, 0x303030, 0x303030);
195
- gridHelper.visible = threeUtils.isDev;
196
- this.scene.add(gridHelper);
207
+ if (threeUtils.isDev) {
208
+ this.scene.add(gridHelper);
209
+ }
197
210
  return gridHelper;
198
211
  })();
199
212
 
200
213
  //坐标轴线
201
214
  axesHelper = (() => {
202
215
  const axesHelper = new AxesHelper(10000);
203
- axesHelper.visible = threeUtils.isDev;
204
- this.scene.add(axesHelper);
216
+ if (threeUtils.isDev) {
217
+ this.scene.add(axesHelper);
218
+ }
205
219
  return axesHelper;
206
220
  })();
207
221
 
@@ -323,8 +337,6 @@ export default class ThreeBase extends EventDispatcher {
323
337
  stopRender() {
324
338
  threeUtils.removeEventListener("requestAnimationFrame", this.renderBindThis);
325
339
  this.renderer.forceContextLoss();
326
- // 标记上下文被销毁了
327
- this.isRendererContextLost = true;
328
340
  this.setSize(100, 100);
329
341
  this.renderer.domElement.style.opacity = "0";
330
342
  }
@@ -363,21 +375,19 @@ export default class ThreeBase extends EventDispatcher {
363
375
  // 渲染场景
364
376
  this.dispatchEvent({ type: "beforeRender" });
365
377
 
366
- this.renderer.setRenderTarget(this.baseRenderTarget);
378
+ // this.renderer.setRenderTarget(this.baseRenderTarget);
367
379
  this.renderer.clear();
368
380
  this.renderer.render(this.scene, this.camera);
369
381
 
370
- this.renderer.setRenderTarget(null);
371
- this.renderer.clear();
382
+ // this.renderer.setRenderTarget(null);
383
+ // this.renderer.clear();
372
384
 
373
385
  //TODO 渲染了2次, 还有优化空间
374
386
  // this.renderer.setScissorTest(false);
375
387
  // this.renderRendererTarget(this.baseRenderTarget);
376
388
  // this.renderer.setScissorTest(true);
377
- // this.renderer.setScissor(0, 0, 512, 1000);
378
- this.renderer.render(this.scene, this.camera);
379
-
380
-
389
+ // this.renderer.setScissor(0, 0, 800, 1000);
390
+ // this.renderer.render(this.scene, this.camera);
381
391
 
382
392
  // 查找需要绘制描边的对象,并且绘制描边
383
393
  this.scene.traverse(obj => {
package/package.json CHANGED
@@ -1,7 +1,10 @@
1
1
  {
2
2
  "name": "three-base",
3
- "version": "2.0.19",
3
+ "version": "2.0.20",
4
4
  "description": "three 3d three-base",
5
+ "publishConfig": {
6
+ "registry": "https://registry.npmjs.org/"
7
+ },
5
8
  "repository": {
6
9
  "type": "git",
7
10
  "url": "https://gitee.com/drm/three-base"
@@ -40,4 +43,4 @@
40
43
  "vite": "*",
41
44
  "html2canvas": "^1.4.1"
42
45
  }
43
- }
46
+ }
package/pass/glow_pass.js CHANGED
@@ -474,6 +474,7 @@ export default function glow_pass(renderer, camera, object3d, baseDepthTexture)
474
474
  const originRenderTarget = renderer.getRenderTarget();
475
475
  // 设置选中目标的帧缓冲区
476
476
  renderer.getSize(size);
477
+ size.multiplyScalar(window.devicePixelRatio);
477
478
  selectTextureTarget.setSize(size.x, size.y);
478
479
  selectDethpTestTextureTarget.setSize(size.x, size.y);
479
480
  blur1TextureTarget.setSize(size.x, size.y);
package/pass/glow_pass.ts CHANGED
@@ -495,6 +495,7 @@ export default function glow_pass(renderer: WebGLRenderer, camera: Camera, objec
495
495
 
496
496
  // 设置选中目标的帧缓冲区
497
497
  renderer.getSize(size);
498
+ size.multiplyScalar(window.devicePixelRatio);
498
499
  selectTextureTarget.setSize(size.x, size.y);
499
500
  selectDethpTestTextureTarget.setSize(size.x, size.y);
500
501
  blur1TextureTarget.setSize(size.x, size.y);
@@ -470,6 +470,7 @@ export default function stroke_pass(renderer, camera, object3d, baseDepthTexture
470
470
  const originRenderTarget = renderer.getRenderTarget();
471
471
  // 设置选中目标的帧缓冲区
472
472
  renderer.getSize(size);
473
+ size.multiplyScalar(window.devicePixelRatio);
473
474
  selectTextureTarget.setSize(size.x, size.y);
474
475
  selectDethpTestTextureTarget.setSize(size.x, size.y);
475
476
  blur1TextureTarget.setSize(size.x, size.y);
@@ -489,6 +489,7 @@ export default function stroke_pass(renderer: WebGLRenderer, camera: Camera, obj
489
489
 
490
490
  // 设置选中目标的帧缓冲区
491
491
  renderer.getSize(size);
492
+ size.multiplyScalar(window.devicePixelRatio);
492
493
  selectTextureTarget.setSize(size.x, size.y);
493
494
  selectDethpTestTextureTarget.setSize(size.x, size.y);
494
495
  blur1TextureTarget.setSize(size.x, size.y);
package/threeLoader.d.ts CHANGED
@@ -3,6 +3,7 @@ import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";
3
3
  import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
4
4
  import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader";
5
5
  import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
6
+ import { STLLoader } from "three/examples/jsm/loaders/STLLoader";
6
7
  declare class ThreeLoader extends EventDispatcher {
7
8
  constructor();
8
9
  anisotropy: number;
@@ -12,6 +13,7 @@ declare class ThreeLoader extends EventDispatcher {
12
13
  getTexture(src: string | HTMLCanvasElement): CanvasTexture | Texture;
13
14
  fbxLoader: FBXLoader;
14
15
  objLoader: OBJLoader;
16
+ stlLoader: STLLoader;
15
17
  mtlLoader: MTLLoader;
16
18
  gltfLoader: GLTFLoader;
17
19
  onload: boolean;
package/threeLoader.js CHANGED
@@ -10,6 +10,7 @@ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
10
10
  import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader";
11
11
  import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
12
12
  import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
13
+ import { STLLoader } from "three/examples/jsm/loaders/STLLoader";
13
14
  // 引入静态资源
14
15
  //@ts-ignore
15
16
  import dracoWasmWrapperJS from "./lib/draco/draco_wasm_wrapper.js?url";
@@ -85,6 +86,8 @@ class ThreeLoader extends EventDispatcher {
85
86
  fbxLoader = new FBXLoader();
86
87
  //obj 加载器
87
88
  objLoader = new OBJLoader();
89
+ // stl 加载器
90
+ stlLoader = new STLLoader();
88
91
  // 材质加载器
89
92
  mtlLoader = new MTLLoader();
90
93
  // gltf 加载器
package/threeLoader.ts CHANGED
@@ -11,6 +11,7 @@ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
11
11
  import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader";
12
12
  import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
13
13
  import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
14
+ import { STLLoader } from "three/examples/jsm/loaders/STLLoader";
14
15
 
15
16
  // 引入静态资源
16
17
  //@ts-ignore
@@ -107,6 +108,9 @@ class ThreeLoader extends EventDispatcher {
107
108
  //obj 加载器
108
109
  objLoader = new OBJLoader();
109
110
 
111
+ // stl 加载器
112
+ stlLoader = new STLLoader();
113
+
110
114
  // 材质加载器
111
115
  mtlLoader = new MTLLoader();
112
116