three-base 2.0.98 → 2.0.99
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/ThreeBase.d.ts +2 -2
- package/ThreeBase.js +109 -47
- package/package.json +1 -1
- package/pass/bool_pass.d.ts +0 -0
- package/pass/bool_pass.js +7 -0
- package/pass/cover_pass.d.ts +2 -0
- package/pass/cover_pass.js +124 -0
- package/pass/glow_pass.d.ts +1 -1
- package/pass/glow_pass.js +2 -2
- package/pass/stroke_pass.d.ts +1 -1
- package/pass/stroke_pass.js +2 -2
- package/shaders/copyShader.d.ts +3 -0
- package/shaders/copyShader.js +33 -0
package/ThreeBase.d.ts
CHANGED
|
@@ -45,7 +45,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
45
45
|
position: Vector3;
|
|
46
46
|
center: Vector3;
|
|
47
47
|
}): void;
|
|
48
|
-
setLookAt({ position, center, duration }: {
|
|
48
|
+
setLookAt({ position, center, duration, }: {
|
|
49
49
|
position: Vector3;
|
|
50
50
|
center: Vector3;
|
|
51
51
|
duration?: number;
|
|
@@ -55,7 +55,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
55
55
|
position: Vector3;
|
|
56
56
|
centerPosition: string;
|
|
57
57
|
};
|
|
58
|
-
lookatObjects({ objects, duration, direction, offset, distance }: {
|
|
58
|
+
lookatObjects({ objects, duration, direction, offset, distance, }: {
|
|
59
59
|
objects: Array<Object3D>;
|
|
60
60
|
duration?: number;
|
|
61
61
|
direction?: Vector3;
|
package/ThreeBase.js
CHANGED
|
@@ -2,20 +2,21 @@
|
|
|
2
2
|
* @Author: xiaosihan
|
|
3
3
|
* @Date: 2021-12-20 13:38:22
|
|
4
4
|
* @Last Modified by: xiaosihan
|
|
5
|
-
* @Last Modified time: 2024-
|
|
5
|
+
* @Last Modified time: 2024-09-23 21:20:32
|
|
6
6
|
*/
|
|
7
7
|
import { round } from "lodash";
|
|
8
|
-
import { AxesHelper, Box3, DepthFormat, DepthTexture, EventDispatcher, GridHelper, LinearFilter, MOUSE, Mesh, NoBlending, NormalBlending, OrthographicCamera, PerspectiveCamera, RGBAFormat, Scene, TOUCH, UnsignedShortType, Vector2, Vector3, WebGLRenderTarget, WebGLRenderer } from "three";
|
|
8
|
+
import { AxesHelper, Box3, DepthFormat, DepthTexture, EventDispatcher, GridHelper, LinearFilter, MOUSE, Mesh, NoBlending, NormalBlending, OrthographicCamera, PerspectiveCamera, RGBAFormat, Scene, TOUCH, UnsignedShortType, Vector2, Vector3, WebGLRenderTarget, WebGLRenderer, } from "three";
|
|
9
9
|
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
|
10
10
|
import { degToRad, generateUUID } from "three/src/math/MathUtils";
|
|
11
11
|
import ThreeMouse from "./ThreeMouse";
|
|
12
12
|
import Transition from "./Transition";
|
|
13
13
|
import glow_pass from "./pass/glow_pass";
|
|
14
14
|
import stroke_pass from "./pass/stroke_pass";
|
|
15
|
-
import { clearShader, coptyShader, fullScreenMesh, gaussBlurShader, strokeShader } from "./shaders";
|
|
15
|
+
import { clearShader, coptyShader, fullScreenMesh, gaussBlurShader, strokeShader, } from "./shaders";
|
|
16
16
|
import FXAAShaderMaterial from "./shaders/FXAAShaderMaterial";
|
|
17
17
|
import threeLoader from "./threeLoader";
|
|
18
18
|
import threeUtils from "./threeUtils";
|
|
19
|
+
import cover_pass from "./pass/cover_pass";
|
|
19
20
|
// three.js 的基础对象
|
|
20
21
|
export default class ThreeBase extends EventDispatcher {
|
|
21
22
|
constructor() {
|
|
@@ -56,9 +57,17 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
56
57
|
return baseRenderTarget;
|
|
57
58
|
})();
|
|
58
59
|
// 公用渲染目标1
|
|
59
|
-
renderTarget = new WebGLRenderTarget(128, 128, {
|
|
60
|
+
renderTarget = new WebGLRenderTarget(128, 128, {
|
|
61
|
+
minFilter: LinearFilter,
|
|
62
|
+
magFilter: LinearFilter,
|
|
63
|
+
format: RGBAFormat,
|
|
64
|
+
});
|
|
60
65
|
// 渲染目标2
|
|
61
|
-
renderTarget2 = new WebGLRenderTarget(128, 128, {
|
|
66
|
+
renderTarget2 = new WebGLRenderTarget(128, 128, {
|
|
67
|
+
minFilter: LinearFilter,
|
|
68
|
+
magFilter: LinearFilter,
|
|
69
|
+
format: RGBAFormat,
|
|
70
|
+
});
|
|
62
71
|
// 公用二维向量
|
|
63
72
|
tempVector2 = new Vector2();
|
|
64
73
|
// 公用的三维向量
|
|
@@ -79,11 +88,11 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
79
88
|
});
|
|
80
89
|
renderer.domElement.id = generateUUID();
|
|
81
90
|
//监听上下文的销毁事件
|
|
82
|
-
renderer.domElement.addEventListener(
|
|
91
|
+
renderer.domElement.addEventListener("webglcontextlost", (event) => {
|
|
83
92
|
this.rendererLost = true;
|
|
84
93
|
}, false);
|
|
85
94
|
// 监听上下文的恢复事件
|
|
86
|
-
renderer.domElement.addEventListener(
|
|
95
|
+
renderer.domElement.addEventListener("webglcontextrestored", (event) => {
|
|
87
96
|
this.rendererLost = false;
|
|
88
97
|
}, false);
|
|
89
98
|
renderer.localClippingEnabled = true;
|
|
@@ -263,8 +272,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
263
272
|
})();
|
|
264
273
|
//TODO 设置帧频率 默认50帧
|
|
265
274
|
frame = 50;
|
|
266
|
-
init() {
|
|
267
|
-
}
|
|
275
|
+
init() { }
|
|
268
276
|
// 重置控制器的位置
|
|
269
277
|
resetLookAt({ position = this.perspectiveCamera.position, center = this.controls.target, }) {
|
|
270
278
|
// 停止控制器的惯性
|
|
@@ -273,13 +281,21 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
273
281
|
this.controls.update();
|
|
274
282
|
this.controls.reset();
|
|
275
283
|
this.controls.enableDamping = originEnableDamping;
|
|
276
|
-
this.controlsDistance.reset({
|
|
277
|
-
|
|
278
|
-
|
|
284
|
+
this.controlsDistance.reset({
|
|
285
|
+
distance: new Vector3(position.x, position.y, position.z).distanceTo(new Vector3(center.x, center.y, center.z)),
|
|
286
|
+
});
|
|
287
|
+
position &&
|
|
288
|
+
this.controlsPosition.reset({
|
|
289
|
+
x: position.x,
|
|
290
|
+
y: position.y,
|
|
291
|
+
z: position.z,
|
|
292
|
+
});
|
|
293
|
+
center &&
|
|
294
|
+
this.controlsCenter.reset({ x: center.x, y: center.y, z: center.z });
|
|
279
295
|
this.needRender = true;
|
|
280
296
|
}
|
|
281
297
|
// 设置控制器的位置 以动画的方式移动控制器
|
|
282
|
-
async setLookAt({ position = this.perspectiveCamera.position, center = this.controls.target, duration = 1000 }) {
|
|
298
|
+
async setLookAt({ position = this.perspectiveCamera.position, center = this.controls.target, duration = 1000, }) {
|
|
283
299
|
// 停止控制器的惯性
|
|
284
300
|
const originEnableDamping = this.controls.enableDamping;
|
|
285
301
|
this.controls.saveState();
|
|
@@ -291,38 +307,60 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
291
307
|
// 等待动画执行完成
|
|
292
308
|
await Promise.all([
|
|
293
309
|
new Promise(async (resolve, reject) => {
|
|
294
|
-
this.controlsDistance.setDuration(duration).reset({
|
|
295
|
-
|
|
310
|
+
this.controlsDistance.setDuration(duration).reset({
|
|
311
|
+
distance: this.perspectiveCamera.position.distanceTo(this.controls.target),
|
|
312
|
+
});
|
|
313
|
+
await this.controlsDistance.set({
|
|
314
|
+
distance: new Vector3(position.x, position.y, position.z).distanceTo(new Vector3(center.x, center.y, center.z)),
|
|
315
|
+
});
|
|
296
316
|
resolve();
|
|
297
317
|
}),
|
|
298
318
|
new Promise(async (resolve, reject) => {
|
|
299
|
-
this.controlsPosition.setDuration(duration).reset({
|
|
300
|
-
|
|
319
|
+
this.controlsPosition.setDuration(duration).reset({
|
|
320
|
+
x: currentPosition.x,
|
|
321
|
+
y: currentPosition.y,
|
|
322
|
+
z: currentPosition.z,
|
|
323
|
+
});
|
|
324
|
+
await this.controlsPosition.set({
|
|
325
|
+
x: position.x,
|
|
326
|
+
y: position.y,
|
|
327
|
+
z: position.z,
|
|
328
|
+
});
|
|
301
329
|
resolve();
|
|
302
330
|
}),
|
|
303
331
|
new Promise(async (resolve, reject) => {
|
|
304
|
-
this.controlsCenter.setDuration(duration).reset({
|
|
305
|
-
|
|
332
|
+
this.controlsCenter.setDuration(duration).reset({
|
|
333
|
+
x: currentCenter.x,
|
|
334
|
+
y: currentCenter.y,
|
|
335
|
+
z: currentCenter.z,
|
|
336
|
+
});
|
|
337
|
+
await this.controlsCenter.set({
|
|
338
|
+
x: center.x,
|
|
339
|
+
y: center.y,
|
|
340
|
+
z: center.z,
|
|
341
|
+
});
|
|
306
342
|
resolve();
|
|
307
|
-
})
|
|
343
|
+
}),
|
|
308
344
|
]);
|
|
309
345
|
}
|
|
310
346
|
// 获取控制的位置和朝向 保留3位小数
|
|
311
347
|
getLookAt() {
|
|
312
348
|
//判断需要使用那个相机
|
|
313
|
-
const position = this.perspectiveCamera.position
|
|
314
|
-
|
|
349
|
+
const position = this.perspectiveCamera.position
|
|
350
|
+
.toArray()
|
|
351
|
+
.map((v) => round(v, 3));
|
|
352
|
+
const center = this.controls.target.toArray().map((v) => round(v, 3));
|
|
315
353
|
return {
|
|
316
354
|
center: new Vector3(...center),
|
|
317
355
|
position: new Vector3(...position),
|
|
318
|
-
centerPosition: `center: new Vector3(${center.join(",")}),position: new Vector3(${position.join(",")})
|
|
356
|
+
centerPosition: `center: new Vector3(${center.join(",")}),position: new Vector3(${position.join(",")})`,
|
|
319
357
|
};
|
|
320
358
|
}
|
|
321
359
|
// 查看对象
|
|
322
|
-
lookatObjects({ objects, duration = 1000, direction = new Vector3(0.3, 0.3, 1), offset = new Vector3(0, 0, 0), distance = 1 }) {
|
|
360
|
+
lookatObjects({ objects, duration = 1000, direction = new Vector3(0.3, 0.3, 1), offset = new Vector3(0, 0, 0), distance = 1, }) {
|
|
323
361
|
const box3 = new Box3();
|
|
324
|
-
objects.map(o => {
|
|
325
|
-
o.traverse(oo => {
|
|
362
|
+
objects.map((o) => {
|
|
363
|
+
o.traverse((oo) => {
|
|
326
364
|
box3.expandByObject(oo);
|
|
327
365
|
});
|
|
328
366
|
});
|
|
@@ -334,7 +372,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
334
372
|
const modelSize = size.length() * distance;
|
|
335
373
|
if (this.cameraType === "perspectiveCamera") {
|
|
336
374
|
const { fov } = this.getCamera();
|
|
337
|
-
const cameraDistance = modelSize / (2 * Math.tan(fov * Math.PI / 360));
|
|
375
|
+
const cameraDistance = modelSize / (2 * Math.tan((fov * Math.PI) / 360));
|
|
338
376
|
const position = direction.setLength(cameraDistance).add(center);
|
|
339
377
|
this.setLookAt({ center, position, duration });
|
|
340
378
|
}
|
|
@@ -355,7 +393,11 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
355
393
|
setControlType(controlType) {
|
|
356
394
|
if (controlType === "OrbitControls") {
|
|
357
395
|
this.controls.screenSpacePanning = this.originScreenSpacePanning;
|
|
358
|
-
this.controls.mouseButtons = {
|
|
396
|
+
this.controls.mouseButtons = {
|
|
397
|
+
LEFT: MOUSE.ROTATE,
|
|
398
|
+
MIDDLE: MOUSE.DOLLY,
|
|
399
|
+
RIGHT: MOUSE.PAN,
|
|
400
|
+
};
|
|
359
401
|
this.controls.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN };
|
|
360
402
|
}
|
|
361
403
|
else if (controlType === "MapControls") {
|
|
@@ -383,14 +425,18 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
383
425
|
}
|
|
384
426
|
// 判断是否有 发光和描边等对象 以便判断是否需要 渲染深度纹理
|
|
385
427
|
hasPass() {
|
|
386
|
-
let
|
|
387
|
-
this.scene.traverse(obj => {
|
|
388
|
-
const { stroke_enable = false, stroke_width = 1, glow_enable = false, glow_width = 1
|
|
389
|
-
|
|
390
|
-
|
|
428
|
+
let hasPass = false;
|
|
429
|
+
this.scene.traverse((obj) => {
|
|
430
|
+
const { stroke_enable = false, stroke_width = 1, glow_enable = false, glow_width = 1, cover_enable = false, //颜色覆盖
|
|
431
|
+
cover_opacity = 0, //透明度
|
|
432
|
+
} = obj.userData;
|
|
433
|
+
if ((stroke_enable && stroke_width > 0) ||
|
|
434
|
+
(glow_enable && glow_width > 0) ||
|
|
435
|
+
(cover_enable && cover_opacity > 0)) {
|
|
436
|
+
hasPass = true;
|
|
391
437
|
}
|
|
392
438
|
});
|
|
393
|
-
return
|
|
439
|
+
return hasPass;
|
|
394
440
|
}
|
|
395
441
|
// 渲染场景
|
|
396
442
|
render() {
|
|
@@ -403,23 +449,33 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
403
449
|
if (this.cameraType === "perspectiveCamera") {
|
|
404
450
|
const { center } = this.getLookAt();
|
|
405
451
|
const { fov } = this.perspectiveCamera;
|
|
406
|
-
const distaned = this.perspectiveCamera.position
|
|
452
|
+
const distaned = this.perspectiveCamera.position
|
|
453
|
+
.clone()
|
|
454
|
+
.sub(center)
|
|
455
|
+
.length();
|
|
407
456
|
const zoom = 1 / (Math.tan(degToRad(fov) / 2) * distaned);
|
|
408
457
|
this.orthographicCamera.zoom = zoom;
|
|
409
|
-
this.orthographicCamera.position
|
|
458
|
+
this.orthographicCamera.position
|
|
459
|
+
.copy(this.perspectiveCamera.position.clone().sub(center))
|
|
460
|
+
.setLength(2500)
|
|
461
|
+
.add(center);
|
|
410
462
|
}
|
|
411
463
|
else if (this.cameraType === "orthographicCamera") {
|
|
412
464
|
const { center } = this.getLookAt();
|
|
413
465
|
const { fov } = this.perspectiveCamera;
|
|
414
466
|
const { zoom } = this.orthographicCamera;
|
|
415
|
-
const distaned =
|
|
416
|
-
this.perspectiveCamera.position
|
|
467
|
+
const distaned = 1 / zoom / Math.tan(degToRad(fov) / 2);
|
|
468
|
+
this.perspectiveCamera.position
|
|
469
|
+
.copy(this.orthographicCamera.position.clone().sub(center))
|
|
470
|
+
.setLength(distaned)
|
|
471
|
+
.add(center);
|
|
417
472
|
}
|
|
418
473
|
//判断需要使用那个相机
|
|
419
474
|
const camera = this.getCamera();
|
|
420
475
|
//判断尺寸发生改变时重置尺寸
|
|
421
476
|
const parentNode = this.renderer.domElement.parentNode;
|
|
422
|
-
if (parentNode.clientWidth !== this.size.x ||
|
|
477
|
+
if (parentNode.clientWidth !== this.size.x ||
|
|
478
|
+
parentNode.clientHeight !== this.size.y) {
|
|
423
479
|
this.setSize(parentNode.clientWidth, parentNode.clientHeight);
|
|
424
480
|
}
|
|
425
481
|
// 分发鼠标事件
|
|
@@ -447,9 +503,10 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
447
503
|
this.renderer.render(this.scene, camera);
|
|
448
504
|
if (hasPass) {
|
|
449
505
|
// 查找需要绘制描边的对象,并且绘制描边
|
|
450
|
-
this.scene.traverseVisible(obj => {
|
|
506
|
+
this.scene.traverseVisible((obj) => {
|
|
451
507
|
stroke_pass(this.renderer, camera, obj, this.baseDepthTexture);
|
|
452
508
|
glow_pass(this.renderer, camera, obj, this.baseDepthTexture);
|
|
509
|
+
cover_pass(this.renderer, camera, obj, this.baseDepthTexture);
|
|
453
510
|
});
|
|
454
511
|
}
|
|
455
512
|
this.dispatchEvent({ type: "afterRender" });
|
|
@@ -459,7 +516,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
459
516
|
async getThumbBlob() {
|
|
460
517
|
this.render();
|
|
461
518
|
const blob = await new Promise((resolve, reject) => {
|
|
462
|
-
this.renderer.domElement.toBlob(blob => {
|
|
519
|
+
this.renderer.domElement.toBlob((blob) => {
|
|
463
520
|
resolve(blob);
|
|
464
521
|
}, "image/png", 1);
|
|
465
522
|
});
|
|
@@ -468,20 +525,20 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
468
525
|
//获取渲染图base64
|
|
469
526
|
getThumbBase64() {
|
|
470
527
|
this.render();
|
|
471
|
-
const base64 = this.renderer.domElement.toDataURL(
|
|
528
|
+
const base64 = this.renderer.domElement.toDataURL("image/png");
|
|
472
529
|
return base64;
|
|
473
530
|
}
|
|
474
531
|
//获取渲染图文件对象
|
|
475
532
|
async getThumbFile() {
|
|
476
533
|
const blob = await this.getThumbBlob();
|
|
477
|
-
const file = new File([blob],
|
|
534
|
+
const file = new File([blob], "thumb.png", { type: blob.type });
|
|
478
535
|
return file;
|
|
479
536
|
}
|
|
480
537
|
// 下载渲染图
|
|
481
538
|
async download(fileName = "download") {
|
|
482
539
|
this.render();
|
|
483
540
|
const blob = await this.getThumbBlob();
|
|
484
|
-
const base64 = this.renderer.domElement.toDataURL(
|
|
541
|
+
const base64 = this.renderer.domElement.toDataURL("image/png");
|
|
485
542
|
let saveLink = document.createElement("a");
|
|
486
543
|
saveLink.download = `${fileName}.png`;
|
|
487
544
|
saveLink.href = URL.createObjectURL(blob);
|
|
@@ -489,12 +546,17 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
489
546
|
saveLink.click();
|
|
490
547
|
}
|
|
491
548
|
_preMesh = new Mesh();
|
|
492
|
-
_preRT = new WebGLRenderTarget(128, 128, {
|
|
549
|
+
_preRT = new WebGLRenderTarget(128, 128, {
|
|
550
|
+
minFilter: LinearFilter,
|
|
551
|
+
magFilter: LinearFilter,
|
|
552
|
+
format: RGBAFormat,
|
|
553
|
+
});
|
|
493
554
|
//预加载纹理图片
|
|
494
555
|
async preloadTexture(src) {
|
|
495
556
|
const texture = threeLoader.getTexture(src);
|
|
496
|
-
while (texture && !texture.image ||
|
|
497
|
-
|
|
557
|
+
while ((texture && !texture.image) ||
|
|
558
|
+
!texture.image.complete) {
|
|
559
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
498
560
|
}
|
|
499
561
|
// 添加到计划任务中去
|
|
500
562
|
threeUtils.addWork(() => {
|
package/package.json
CHANGED
|
File without changes
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2024-09-23 21:07:06
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2024-09-23 21:53:12
|
|
6
|
+
*/
|
|
7
|
+
/*
|
|
8
|
+
* @Author: xiaosihan
|
|
9
|
+
* @Date: 2023-05-09 00:35:17
|
|
10
|
+
* @Last Modified by: xiaosihan
|
|
11
|
+
* @Last Modified time: 2023-05-09 02:33:28
|
|
12
|
+
*/
|
|
13
|
+
import { Color, DepthFormat, DepthTexture, LinearFilter, NoBlending, RGBAFormat, Scene, ShaderChunk, ShaderMaterial, UnsignedShortType, Vector2, WebGLRenderTarget } from "three";
|
|
14
|
+
import copyShader from "../shaders/copyShader";
|
|
15
|
+
import FullScreenQuad from "./FullScreenQuad";
|
|
16
|
+
// 选中对象的深度纹理
|
|
17
|
+
const selectDepthTexture = (() => {
|
|
18
|
+
const baseDepthTexture = new DepthTexture(4096, 4096);
|
|
19
|
+
baseDepthTexture.format = DepthFormat;
|
|
20
|
+
baseDepthTexture.type = UnsignedShortType;
|
|
21
|
+
baseDepthTexture.anisotropy = 16;
|
|
22
|
+
return baseDepthTexture;
|
|
23
|
+
})();
|
|
24
|
+
// 选中对象的纹理
|
|
25
|
+
const selectTextureTarget = new WebGLRenderTarget(512, 512, {
|
|
26
|
+
minFilter: LinearFilter,
|
|
27
|
+
magFilter: LinearFilter,
|
|
28
|
+
format: RGBAFormat,
|
|
29
|
+
depthTexture: selectDepthTexture,
|
|
30
|
+
anisotropy: 16,
|
|
31
|
+
});
|
|
32
|
+
// 深度测试后的选中纹理
|
|
33
|
+
const selectDethpTestTextureTarget = new WebGLRenderTarget(512, 512, {
|
|
34
|
+
minFilter: LinearFilter,
|
|
35
|
+
magFilter: LinearFilter,
|
|
36
|
+
format: RGBAFormat,
|
|
37
|
+
anisotropy: 16,
|
|
38
|
+
});
|
|
39
|
+
const blur1TextureTarget = new WebGLRenderTarget(512, 512, {
|
|
40
|
+
minFilter: LinearFilter,
|
|
41
|
+
magFilter: LinearFilter,
|
|
42
|
+
format: RGBAFormat,
|
|
43
|
+
});
|
|
44
|
+
const size = new Vector2();
|
|
45
|
+
// 创建一个渲染工具 用于处理纹理
|
|
46
|
+
const fsQuad = new FullScreenQuad(); // 渲染辅助器
|
|
47
|
+
//深度比对纹理
|
|
48
|
+
const depthTestShader = new ShaderMaterial({
|
|
49
|
+
uniforms: {
|
|
50
|
+
color: { value: new Color("#000000") },
|
|
51
|
+
baseDepth: { value: null },
|
|
52
|
+
selectDepth: { value: null }, // 选中的对象深度纹理
|
|
53
|
+
},
|
|
54
|
+
vertexShader: `
|
|
55
|
+
${ShaderChunk.common}
|
|
56
|
+
${ShaderChunk.logdepthbuf_pars_vertex}
|
|
57
|
+
varying vec2 vUv;
|
|
58
|
+
void main() {
|
|
59
|
+
vUv = uv;
|
|
60
|
+
// gl_Position = vec4(position, 1.0);
|
|
61
|
+
// gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4(position, 1.0);
|
|
62
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
63
|
+
${ShaderChunk.logdepthbuf_vertex}
|
|
64
|
+
}
|
|
65
|
+
`,
|
|
66
|
+
fragmentShader: `
|
|
67
|
+
${ShaderChunk.logdepthbuf_pars_fragment}
|
|
68
|
+
uniform vec3 color;
|
|
69
|
+
uniform sampler2D baseDepth;
|
|
70
|
+
uniform sampler2D selectDepth;
|
|
71
|
+
varying vec2 vUv;
|
|
72
|
+
void main() {
|
|
73
|
+
if(texture2D(baseDepth, vUv).r + 0.0001 < texture2D(selectDepth, vUv).r){
|
|
74
|
+
discard;
|
|
75
|
+
}
|
|
76
|
+
gl_FragColor = vec4(color, 1.0);
|
|
77
|
+
${ShaderChunk.logdepthbuf_fragment}
|
|
78
|
+
}
|
|
79
|
+
`,
|
|
80
|
+
blending: NoBlending,
|
|
81
|
+
depthTest: true,
|
|
82
|
+
depthWrite: true,
|
|
83
|
+
transparent: true,
|
|
84
|
+
});
|
|
85
|
+
// 场景对象
|
|
86
|
+
const scene = new Scene();
|
|
87
|
+
// 给模型覆盖一层颜色 后处理通道
|
|
88
|
+
export default function cover_pass(renderer, camera, object3d, baseDepthTexture) {
|
|
89
|
+
const { cover_enable = false, cover_color = "#04fa12", cover_opacity = 1, } = object3d.userData;
|
|
90
|
+
if (!cover_enable || cover_opacity === 0) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
// 保存原帧缓冲区
|
|
94
|
+
const originRenderTarget = renderer.getRenderTarget();
|
|
95
|
+
// 设置选中目标的帧缓冲区
|
|
96
|
+
renderer.getSize(size);
|
|
97
|
+
size.multiplyScalar(window.devicePixelRatio);
|
|
98
|
+
selectTextureTarget.setSize(size.x, size.y);
|
|
99
|
+
selectDethpTestTextureTarget.setSize(size.x, size.y);
|
|
100
|
+
blur1TextureTarget.setSize(size.x, size.y);
|
|
101
|
+
renderer.setRenderTarget(selectTextureTarget);
|
|
102
|
+
scene.children = [object3d];
|
|
103
|
+
renderer.clear();
|
|
104
|
+
renderer.render(scene, camera);
|
|
105
|
+
//深度测试
|
|
106
|
+
renderer.setRenderTarget(selectDethpTestTextureTarget);
|
|
107
|
+
renderer.clear();
|
|
108
|
+
depthTestShader.uniforms.color.value.set(cover_color);
|
|
109
|
+
depthTestShader.uniforms.baseDepth.value = baseDepthTexture;
|
|
110
|
+
depthTestShader.uniforms.selectDepth.value = selectDepthTexture;
|
|
111
|
+
fsQuad.render(renderer, depthTestShader);
|
|
112
|
+
// 颜色覆盖绘制到着色器
|
|
113
|
+
renderer.setRenderTarget(originRenderTarget);
|
|
114
|
+
renderer.clearDepth();
|
|
115
|
+
copyShader.uniforms.map.value = selectDethpTestTextureTarget.texture;
|
|
116
|
+
copyShader.uniforms.opacity.value = cover_opacity;
|
|
117
|
+
fsQuad.render(renderer, copyShader);
|
|
118
|
+
// 调试代码
|
|
119
|
+
// renderer.setRenderTarget(null);
|
|
120
|
+
// renderer.clearDepth();
|
|
121
|
+
// copyShader.uniforms.tDiffuse.value = blur2TextureTarget.texture;
|
|
122
|
+
// fsQuad.render(renderer, copyShader);
|
|
123
|
+
// return;
|
|
124
|
+
}
|
package/pass/glow_pass.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Camera, Object3D, WebGLRenderer
|
|
1
|
+
import { Camera, DepthTexture, Object3D, WebGLRenderer } from "three";
|
|
2
2
|
export default function glow_pass(renderer: WebGLRenderer, camera: Camera, object3d: Object3D, baseDepthTexture: DepthTexture): void;
|
package/pass/glow_pass.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* @Author: xiaosihan
|
|
3
3
|
* @Date: 2023-05-09 00:35:17
|
|
4
4
|
* @Last Modified by: xiaosihan
|
|
5
|
-
* @Last Modified time:
|
|
5
|
+
* @Last Modified time: 2024-09-23 22:00:48
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { Color, DepthFormat, DepthTexture, LinearFilter, NoBlending, NormalBlending, RGBAFormat, RawShaderMaterial, Scene, ShaderChunk, ShaderMaterial, UnsignedShortType, Vector2, WebGLRenderTarget } from "three";
|
|
8
8
|
import FullScreenQuad from "./FullScreenQuad";
|
|
9
9
|
// 选中对象的深度纹理
|
|
10
10
|
const selectDepthTexture = (() => {
|
package/pass/stroke_pass.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Camera, Object3D, WebGLRenderer
|
|
1
|
+
import { Camera, DepthTexture, Object3D, WebGLRenderer } from "three";
|
|
2
2
|
export default function stroke_pass(renderer: WebGLRenderer, camera: Camera, object3d: Object3D, baseDepthTexture: DepthTexture): void;
|
package/pass/stroke_pass.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* @Author: xiaosihan
|
|
3
3
|
* @Date: 2023-05-09 00:35:17
|
|
4
4
|
* @Last Modified by: xiaosihan
|
|
5
|
-
* @Last Modified time:
|
|
5
|
+
* @Last Modified time: 2024-09-23 22:00:54
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { Color, DepthFormat, DepthTexture, LinearFilter, NoBlending, NormalBlending, RGBAFormat, RawShaderMaterial, Scene, ShaderChunk, ShaderMaterial, UnsignedShortType, Vector2, WebGLRenderTarget } from "three";
|
|
8
8
|
import FullScreenQuad from "./FullScreenQuad";
|
|
9
9
|
// 选中对象的深度纹理
|
|
10
10
|
const selectDepthTexture = (() => {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ShaderChunk, ShaderMaterial } from "three";
|
|
2
|
+
// 拷贝着色器
|
|
3
|
+
const copyShader = new ShaderMaterial({
|
|
4
|
+
uniforms: {
|
|
5
|
+
map: { value: null },
|
|
6
|
+
opacity: { value: 1 }, // 透明度
|
|
7
|
+
},
|
|
8
|
+
vertexShader: `
|
|
9
|
+
${ShaderChunk.common}
|
|
10
|
+
${ShaderChunk.logdepthbuf_pars_vertex}
|
|
11
|
+
varying vec2 vUv;
|
|
12
|
+
void main() {
|
|
13
|
+
vUv = uv;
|
|
14
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
15
|
+
${ShaderChunk.logdepthbuf_vertex}
|
|
16
|
+
}
|
|
17
|
+
`,
|
|
18
|
+
fragmentShader: `
|
|
19
|
+
${ShaderChunk.logdepthbuf_pars_fragment}
|
|
20
|
+
uniform float opacity;
|
|
21
|
+
uniform sampler2D map;
|
|
22
|
+
varying vec2 vUv;
|
|
23
|
+
void main() {
|
|
24
|
+
gl_FragColor = texture2D(map, vUv);
|
|
25
|
+
gl_FragColor.a *= opacity;
|
|
26
|
+
${ShaderChunk.logdepthbuf_fragment}
|
|
27
|
+
}
|
|
28
|
+
`,
|
|
29
|
+
depthTest: true,
|
|
30
|
+
depthWrite: true,
|
|
31
|
+
transparent: true,
|
|
32
|
+
});
|
|
33
|
+
export default copyShader;
|