three-base 2.0.115 → 2.0.117
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/ExtrudeMesh.d.ts +1 -0
- package/ExtrudeMesh.js +7 -4
- package/PipeMesh/PathGeometry.d.ts +2 -0
- package/PipeMesh/PathGeometry.js +3 -0
- package/ThreeBase.d.ts +1 -0
- package/ThreeBase.js +52 -24
- package/ThreeMouse.d.ts +11 -12
- package/ThreeMouse.js +60 -38
- package/package.json +1 -1
- package/pass/glow_pass.js +3 -5
- package/pass/stroke_pass.js +14 -15
- package/shaders/baseTextureToRenderShader.d.ts +2 -0
- package/shaders/baseTextureToRenderShader.js +237 -0
- package/shaders.d.ts +0 -3
- package/shaders.js +1 -161
package/ExtrudeMesh.d.ts
CHANGED
|
@@ -34,6 +34,7 @@ export default class ExtrudeMesh extends Mesh<BufferGeometry, Material> {
|
|
|
34
34
|
static temp2Matrix4: Matrix4;
|
|
35
35
|
static temp3Matrix4: Matrix4;
|
|
36
36
|
constructor(props: ExtrudeMeshProps, material?: Material);
|
|
37
|
+
shapePathWidth: number;
|
|
37
38
|
pointerWidthRadius: Array<{
|
|
38
39
|
vector3: [number, number, number];
|
|
39
40
|
matrix: [
|
package/ExtrudeMesh.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author: xiaosihan
|
|
3
3
|
* @Date: 2022-06-08 14:20:52
|
|
4
4
|
* @Last Modified by: xiaosihan
|
|
5
|
-
* @Last Modified time:
|
|
5
|
+
* @Last Modified time: 2025-01-17 20:42:22
|
|
6
6
|
*/
|
|
7
7
|
import { clamp, cloneDeep, filter, first, get, isNumber, last } from "lodash";
|
|
8
8
|
import { BufferAttribute, BufferGeometry, Matrix4, Mesh, Vector2, Vector3 } from "three";
|
|
@@ -32,6 +32,8 @@ export default class ExtrudeMesh extends Mesh {
|
|
|
32
32
|
super(undefined, material);
|
|
33
33
|
this.updateGeometry(props);
|
|
34
34
|
}
|
|
35
|
+
//宽度
|
|
36
|
+
shapePathWidth = 1;
|
|
35
37
|
// 通过 props.paths 和圆角属性 计算出来的 最终路径
|
|
36
38
|
pointerWidthRadius = [];
|
|
37
39
|
// 通过2个顶点和缩放值计算矩阵
|
|
@@ -155,16 +157,16 @@ export default class ExtrudeMesh extends Mesh {
|
|
|
155
157
|
.toArray()
|
|
156
158
|
});
|
|
157
159
|
}
|
|
158
|
-
else if (segments === 0) { // 分段数为0时不分段
|
|
160
|
+
else if (segments === 0) { // 分段数为0时不分段 并在前后各加一个点
|
|
159
161
|
let { x = 1, y = 1 } = scale;
|
|
160
162
|
this.pointerWidthRadius.push({
|
|
161
163
|
vector3,
|
|
162
|
-
matrix: this.computerMatrix((v2Inv1Left ? circleCenter.toArray() : vector3), (v2Inv1Left ? vector3 : circleCenter.toArray()), [1, y, x])
|
|
164
|
+
matrix: this.computerMatrix((v2Inv1Left ? circleCenter.toArray() : vector3), (v2Inv1Left ? vector3 : circleCenter.toArray()), [1, y, x / Math.sin(innerAngle / 2)])
|
|
163
165
|
});
|
|
164
166
|
}
|
|
165
167
|
else {
|
|
166
168
|
for (let ii = 0; ii <= segments; ii++) {
|
|
167
|
-
//
|
|
169
|
+
// 圆角计算的第n个点的角度
|
|
168
170
|
let Aa = ii * ((Math.PI - innerAngle) / segments);
|
|
169
171
|
//半径对角
|
|
170
172
|
let Cc = Math.PI - Aa - (innerAngle / 2);
|
|
@@ -330,6 +332,7 @@ export default class ExtrudeMesh extends Mesh {
|
|
|
330
332
|
//设置模型
|
|
331
333
|
updateGeometry(props) {
|
|
332
334
|
const { paths, shapePath, closed } = props;
|
|
335
|
+
this.shapePathWidth = Math.max(...shapePath.map(path => path[0])) - Math.min(...shapePath.map(path => path[0]));
|
|
333
336
|
// 计算圆角路径
|
|
334
337
|
this.computerPointerWidthRadius(paths, closed);
|
|
335
338
|
//网格模型的每个顶点位置
|
|
@@ -25,6 +25,8 @@ declare class PathGeometry extends BufferGeometry {
|
|
|
25
25
|
* @param {Boolean} [generateUv2=false]
|
|
26
26
|
*/
|
|
27
27
|
constructor(initData: PathGeometryParam, generateUv2?: boolean);
|
|
28
|
+
computeBoundsTree: any;
|
|
29
|
+
disposeBoundsTree: any;
|
|
28
30
|
_initByMaxVertex(maxVertex: number, generateUv2: boolean): void;
|
|
29
31
|
_initByData(pathPointList: PathPointList, options: Options, usage: Usage, generateUv2: boolean): void;
|
|
30
32
|
/**
|
package/PipeMesh/PathGeometry.js
CHANGED
|
@@ -3,6 +3,7 @@ import { PathPoint } from './PathPoint.js';
|
|
|
3
3
|
import { BufferGeometry } from 'three/src/core/BufferGeometry.js';
|
|
4
4
|
import { BufferAttribute } from 'three/src/core/BufferAttribute.js';
|
|
5
5
|
import { Vector3 } from 'three/src/math/Vector3.js';
|
|
6
|
+
import { computeBoundsTree, disposeBoundsTree } from 'three-mesh-bvh';
|
|
6
7
|
/**
|
|
7
8
|
* PathGeometry
|
|
8
9
|
*/
|
|
@@ -15,6 +16,8 @@ class PathGeometry extends BufferGeometry {
|
|
|
15
16
|
super();
|
|
16
17
|
this._initByData(initData.pathPointList, initData.options, initData.usage, generateUv2);
|
|
17
18
|
}
|
|
19
|
+
computeBoundsTree = computeBoundsTree.bind(this);
|
|
20
|
+
disposeBoundsTree = disposeBoundsTree.bind(this);
|
|
18
21
|
_initByMaxVertex(maxVertex, generateUv2) {
|
|
19
22
|
this.setAttribute('position', new BufferAttribute(new Float32Array(maxVertex * 3), 3).setUsage(DynamicDrawUsage));
|
|
20
23
|
this.setAttribute('normal', new BufferAttribute(new Float32Array(maxVertex * 3), 3).setUsage(DynamicDrawUsage));
|
package/ThreeBase.d.ts
CHANGED
package/ThreeBase.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author: xiaosihan
|
|
3
3
|
* @Date: 2021-12-20 13:38:22
|
|
4
4
|
* @Last Modified by: xiaosihan
|
|
5
|
-
* @Last Modified time: 2025-01-17
|
|
5
|
+
* @Last Modified time: 2025-01-17 11:07:38
|
|
6
6
|
*/
|
|
7
7
|
import { round } from "lodash";
|
|
8
8
|
import { AxesHelper, Box3, DepthFormat, DepthTexture, EventDispatcher, GridHelper, LinearFilter, MOUSE, NoBlending, NormalBlending, OrthographicCamera, PerspectiveCamera, RGBAFormat, ReinhardToneMapping, SRGBColorSpace, Scene, TOUCH, UnsignedShortType, Vector2, Vector3, WebGLRenderTarget, WebGLRenderer, } from "three";
|
|
@@ -10,13 +10,14 @@ 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
|
+
import bloom_pass from "./pass/bloom_pass";
|
|
14
|
+
import cover_pass from "./pass/cover_pass";
|
|
13
15
|
import glow_pass from "./pass/glow_pass";
|
|
14
16
|
import stroke_pass from "./pass/stroke_pass";
|
|
15
|
-
import {
|
|
17
|
+
import { copyShader, fullScreenMesh } from "./shaders";
|
|
18
|
+
import { baseTextureToRenderShader } from "./shaders/baseTextureToRenderShader";
|
|
16
19
|
import threeLoader from "./threeLoader";
|
|
17
20
|
import threeUtils from "./threeUtils";
|
|
18
|
-
import cover_pass from "./pass/cover_pass";
|
|
19
|
-
import bloom_pass from "./pass/bloom_pass";
|
|
20
21
|
// three.js 的基础对象
|
|
21
22
|
export default class ThreeBase extends EventDispatcher {
|
|
22
23
|
constructor() {
|
|
@@ -193,7 +194,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
193
194
|
this.renderer.setPixelRatio(window.devicePixelRatio);
|
|
194
195
|
this.renderer.setSize(width, height);
|
|
195
196
|
// 设置帧缓存区的尺寸
|
|
196
|
-
this.baseRenderTarget.setSize(width *
|
|
197
|
+
this.baseRenderTarget.setSize(width * window.devicePixelRatio, height * window.devicePixelRatio);
|
|
197
198
|
// 设置深度纹理的尺寸
|
|
198
199
|
this.baseDepthTexture.image.width = width * window.devicePixelRatio;
|
|
199
200
|
this.baseDepthTexture.image.height = height * window.devicePixelRatio;
|
|
@@ -234,12 +235,12 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
234
235
|
// .setLength(distance)
|
|
235
236
|
// .add(this.controls.target);
|
|
236
237
|
// // 创建初始方向向量
|
|
237
|
-
// const directionVecA = new
|
|
238
|
-
// const referenceVecB = new
|
|
238
|
+
// const directionVecA = new Vector3(1, 0, 0); // 需要旋转的初始方向向量
|
|
239
|
+
// const referenceVecB = new Vector3(0, 1, 0); // 参考方向向量,用于确定旋转轴
|
|
239
240
|
// // 归一化参考方向向量
|
|
240
241
|
// referenceVecB.normalize();
|
|
241
242
|
// // 计算旋转轴
|
|
242
|
-
// const axis = new
|
|
243
|
+
// const axis = new Vector3().crossVectors(directionVecA, referenceVecB).normalize();
|
|
243
244
|
// // 计算旋转角度(弧度)
|
|
244
245
|
// const angle = Math.PI / 36; // 旋转角度为5度,Math.PI / 36为弧度
|
|
245
246
|
// // 使用applyAxisAngle方法进行旋转
|
|
@@ -427,6 +428,23 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
427
428
|
this.renderer.domElement.style.opacity = "0";
|
|
428
429
|
}
|
|
429
430
|
}
|
|
431
|
+
//判断是否有特效
|
|
432
|
+
hasPass() {
|
|
433
|
+
let hasPass = false;
|
|
434
|
+
this.scene.traverseVisible((obj) => {
|
|
435
|
+
const { stroke_enable = false, stroke_width = 1, glow_enable = false, glow_width = 1, cover_enable = false, cover_opacity = 1, } = obj.userData;
|
|
436
|
+
if (stroke_enable && stroke_width > 0) {
|
|
437
|
+
hasPass = true;
|
|
438
|
+
}
|
|
439
|
+
if (glow_enable && glow_width > 0) {
|
|
440
|
+
hasPass = true;
|
|
441
|
+
}
|
|
442
|
+
if (cover_enable && cover_opacity > 0) {
|
|
443
|
+
hasPass = true;
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
return hasPass;
|
|
447
|
+
}
|
|
430
448
|
// 渲染场景
|
|
431
449
|
render() {
|
|
432
450
|
// canvas 没有在页面上面的话 就停止渲染
|
|
@@ -479,21 +497,31 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
479
497
|
}
|
|
480
498
|
// 渲染场景
|
|
481
499
|
this.dispatchEvent({ type: "beforeRender" });
|
|
500
|
+
const hasPass = this.hasPass();
|
|
482
501
|
// 把基础场景渲染到 帧缓冲区 在后期通道中会用到
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
502
|
+
if (hasPass) {
|
|
503
|
+
this.renderer.setRenderTarget(this.baseRenderTarget);
|
|
504
|
+
this.renderer.clear();
|
|
505
|
+
this.renderer.render(this.scene, camera);
|
|
506
|
+
// 后处理特效渲染(描边,发光,颜色覆盖,磨砂玻璃,bloom)
|
|
507
|
+
this.scene.traverseVisible((obj) => {
|
|
508
|
+
stroke_pass(this.renderer, camera, obj, this.baseDepthTexture);
|
|
509
|
+
glow_pass(this.renderer, camera, obj, this.baseDepthTexture);
|
|
510
|
+
});
|
|
511
|
+
this.renderer.setRenderTarget(null);
|
|
512
|
+
this.renderer.clear();
|
|
513
|
+
this.renderRendererTarget(this.baseRenderTarget);
|
|
514
|
+
this.scene.traverseVisible((obj) => {
|
|
515
|
+
cover_pass(this.renderer, camera, obj, this.baseDepthTexture);
|
|
516
|
+
});
|
|
517
|
+
//后处理发光特效
|
|
518
|
+
bloom_pass(this.renderer, camera, this.scene, this.baseDepthTexture);
|
|
519
|
+
}
|
|
520
|
+
else {
|
|
521
|
+
this.renderer.setRenderTarget(null);
|
|
522
|
+
this.renderer.clear();
|
|
523
|
+
this.renderer.render(this.scene, camera);
|
|
524
|
+
}
|
|
497
525
|
this.dispatchEvent({ type: "afterRender" });
|
|
498
526
|
}
|
|
499
527
|
renderBindThis = this.render.bind(this);
|
|
@@ -540,8 +568,8 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
540
568
|
}
|
|
541
569
|
//把渲染目标渲染到canvas上
|
|
542
570
|
renderRendererTarget(renderTarget) {
|
|
543
|
-
baseTextureToRenderShader.uniforms.
|
|
544
|
-
baseTextureToRenderShader.uniforms.
|
|
571
|
+
baseTextureToRenderShader.uniforms.resolution.value.set(1 / this.size.x, 1 / this.size.y);
|
|
572
|
+
baseTextureToRenderShader.uniforms.tDiffuse.value = renderTarget.texture;
|
|
545
573
|
fullScreenMesh.render(this.renderer, baseTextureToRenderShader);
|
|
546
574
|
}
|
|
547
575
|
// 渲染纹理
|
package/ThreeMouse.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import type { Intersection } from "three";
|
|
1
|
+
import { Object3D, Raycaster, Scene, Vector2, WebGLRenderer } from "three";
|
|
2
|
+
import { Camera, Intersection, Renderer } from "three";
|
|
4
3
|
export interface ThreeMouseEvent extends Intersection {
|
|
5
4
|
e: MouseEvent;
|
|
6
|
-
renderer:
|
|
7
|
-
camera:
|
|
5
|
+
renderer: Renderer;
|
|
6
|
+
camera: Camera;
|
|
8
7
|
type: string;
|
|
9
8
|
offsetX: number;
|
|
10
9
|
offsetY: number;
|
|
@@ -12,18 +11,18 @@ export interface ThreeMouseEvent extends Intersection {
|
|
|
12
11
|
y: number;
|
|
13
12
|
}
|
|
14
13
|
/**
|
|
15
|
-
*
|
|
14
|
+
* js 专用的鼠标拾取模型对象
|
|
16
15
|
*/
|
|
17
16
|
export default class ThreeMouse {
|
|
18
|
-
constructor(renderer:
|
|
19
|
-
_renderer:
|
|
20
|
-
_camera:
|
|
17
|
+
constructor(renderer: WebGLRenderer, camera: Camera, scene: Scene);
|
|
18
|
+
_renderer: WebGLRenderer;
|
|
19
|
+
_camera: Camera;
|
|
21
20
|
_scene: Scene;
|
|
22
|
-
_mosePosition:
|
|
23
|
-
_mouseDownPosition:
|
|
21
|
+
_mosePosition: Vector2;
|
|
22
|
+
_mouseDownPosition: Vector2;
|
|
24
23
|
_mesh_on?: Object3D;
|
|
25
24
|
_mesh_Down?: Object3D;
|
|
26
|
-
_raycaster:
|
|
25
|
+
_raycaster: Raycaster;
|
|
27
26
|
_frame: number;
|
|
28
27
|
_mouseInRenderer: boolean;
|
|
29
28
|
_mousemoveEvent?: MouseEvent;
|
package/ThreeMouse.js
CHANGED
|
@@ -4,16 +4,14 @@
|
|
|
4
4
|
//
|
|
5
5
|
//
|
|
6
6
|
// 启动鼠标事件
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
7
|
+
import { Raycaster, Vector2 } from "three";
|
|
8
|
+
import { Mesh } from "three";
|
|
9
9
|
import { debounce } from "lodash";
|
|
10
|
-
import { computeBoundsTree, disposeBoundsTree, acceleratedRaycast } from
|
|
10
|
+
import { computeBoundsTree, disposeBoundsTree, acceleratedRaycast, } from "three-mesh-bvh";
|
|
11
11
|
// Add the extension functions
|
|
12
|
-
|
|
13
|
-
THREE.BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree;
|
|
14
|
-
THREE.Mesh.prototype.raycast = acceleratedRaycast;
|
|
12
|
+
Mesh.prototype.raycast = acceleratedRaycast;
|
|
15
13
|
/**
|
|
16
|
-
*
|
|
14
|
+
* js 专用的鼠标拾取模型对象
|
|
17
15
|
*/
|
|
18
16
|
export default class ThreeMouse {
|
|
19
17
|
constructor(renderer, camera, scene) {
|
|
@@ -21,7 +19,9 @@ export default class ThreeMouse {
|
|
|
21
19
|
this._camera = camera;
|
|
22
20
|
this._scene = scene;
|
|
23
21
|
this._frame = this._renderer.info.render.frame;
|
|
24
|
-
this._renderer.domElement.addEventListener("mouseenter", () => {
|
|
22
|
+
this._renderer.domElement.addEventListener("mouseenter", () => {
|
|
23
|
+
this._mouseInRenderer = true;
|
|
24
|
+
}, true); //鼠标进入开启拾取
|
|
25
25
|
this._renderer.domElement.addEventListener("mouseleave", this._mouseleave, true); //鼠标离开停止拾取
|
|
26
26
|
this._renderer.domElement.addEventListener("mousemove", this._mousemove, true); //鼠标移动监听事件
|
|
27
27
|
this._renderer.domElement.addEventListener("pointerdown", this._mousedown, true); //鼠标按下监听事件
|
|
@@ -32,9 +32,9 @@ export default class ThreeMouse {
|
|
|
32
32
|
_camera;
|
|
33
33
|
_scene;
|
|
34
34
|
// 鼠标在渲染器上面的位置
|
|
35
|
-
_mosePosition = new
|
|
35
|
+
_mosePosition = new Vector2(0, 0);
|
|
36
36
|
// 鼠标按下的位置 如果和鼠标弹起的位置相同 才算一次有效的点击事件
|
|
37
|
-
_mouseDownPosition = new
|
|
37
|
+
_mouseDownPosition = new Vector2(0, 0);
|
|
38
38
|
//当前鼠标指针上的对象
|
|
39
39
|
_mesh_on;
|
|
40
40
|
//鼠标按下的对象
|
|
@@ -61,7 +61,6 @@ export default class ThreeMouse {
|
|
|
61
61
|
}
|
|
62
62
|
return intersection;
|
|
63
63
|
}
|
|
64
|
-
;
|
|
65
64
|
// 判断对象上面是否有事件
|
|
66
65
|
hasEvent(object, types = []) {
|
|
67
66
|
if (!object) {
|
|
@@ -71,9 +70,11 @@ export default class ThreeMouse {
|
|
|
71
70
|
if (object["userData"] && object["userData"]["enableEvent"] === false) {
|
|
72
71
|
return false;
|
|
73
72
|
}
|
|
74
|
-
const hasevent = types.some(type => {
|
|
73
|
+
const hasevent = types.some((type) => {
|
|
75
74
|
//@ts-ignore
|
|
76
|
-
if (object["_listeners"] &&
|
|
75
|
+
if (object["_listeners"] &&
|
|
76
|
+
object["_listeners"][type] &&
|
|
77
|
+
object["_listeners"][type][0]) {
|
|
77
78
|
return true;
|
|
78
79
|
}
|
|
79
80
|
// if (object["userData"] && object["userData"]["cursor"]) {
|
|
@@ -100,11 +101,23 @@ export default class ThreeMouse {
|
|
|
100
101
|
dispatchEvent() {
|
|
101
102
|
// 提取有事件的对象
|
|
102
103
|
const meshs = [];
|
|
103
|
-
this._scene.traverseVisible(mesh => {
|
|
104
|
+
this._scene.traverseVisible((mesh) => {
|
|
104
105
|
// 判断对象是否有指定的事件
|
|
105
|
-
if (this.hasCursor(mesh) ||
|
|
106
|
+
if (this.hasCursor(mesh) ||
|
|
107
|
+
this.hasEvent(mesh, [
|
|
108
|
+
"leftclick",
|
|
109
|
+
"rightclick",
|
|
110
|
+
"click",
|
|
111
|
+
"dbclick",
|
|
112
|
+
"mouseenter",
|
|
113
|
+
"mouseleave",
|
|
114
|
+
"mousemove",
|
|
115
|
+
"mousedown",
|
|
116
|
+
"mouseup",
|
|
117
|
+
])) {
|
|
106
118
|
if (mesh.isMesh && !mesh.geometry.boundsTree) {
|
|
107
|
-
mesh.geometry
|
|
119
|
+
computeBoundsTree.apply(mesh.geometry);
|
|
120
|
+
disposeBoundsTree.apply(mesh.geometry);
|
|
108
121
|
}
|
|
109
122
|
meshs.push(mesh);
|
|
110
123
|
}
|
|
@@ -120,6 +133,7 @@ export default class ThreeMouse {
|
|
|
120
133
|
const { face, object } = intersection;
|
|
121
134
|
// face && face.normal.applyMatrix4(object.matrixWorld);
|
|
122
135
|
const MouseEvent = Object.assign(intersection, {
|
|
136
|
+
// 将来可能用到的对象
|
|
123
137
|
e: this._mousemoveEvent,
|
|
124
138
|
renderer: this._renderer,
|
|
125
139
|
camera: this._camera,
|
|
@@ -128,7 +142,7 @@ export default class ThreeMouse {
|
|
|
128
142
|
offsetX: this._mousemoveEvent.offsetX,
|
|
129
143
|
offsetY: this._mousemoveEvent.offsetY,
|
|
130
144
|
x: this._mousemoveEvent.x,
|
|
131
|
-
y: this._mousemoveEvent.y
|
|
145
|
+
y: this._mousemoveEvent.y,
|
|
132
146
|
});
|
|
133
147
|
// 触发滑动事件
|
|
134
148
|
if (this._mesh_on === MouseEvent.object) {
|
|
@@ -150,7 +164,9 @@ export default class ThreeMouse {
|
|
|
150
164
|
}
|
|
151
165
|
this._mesh_on = MouseEvent.object || undefined; // 设置为当前鼠标上的对象
|
|
152
166
|
// 鼠标样式
|
|
153
|
-
if (this._mesh_on &&
|
|
167
|
+
if (this._mesh_on &&
|
|
168
|
+
this._mesh_on.userData &&
|
|
169
|
+
this._mesh_on.userData.cursor) {
|
|
154
170
|
this._renderer.domElement.style.cursor = this._mesh_on.userData.cursor;
|
|
155
171
|
}
|
|
156
172
|
else {
|
|
@@ -169,7 +185,7 @@ export default class ThreeMouse {
|
|
|
169
185
|
offsetX: this._mousemoveEvent.offsetX,
|
|
170
186
|
offsetY: this._mousemoveEvent.offsetY,
|
|
171
187
|
x: this._mousemoveEvent.x,
|
|
172
|
-
y: this._mousemoveEvent.y
|
|
188
|
+
y: this._mousemoveEvent.y,
|
|
173
189
|
});
|
|
174
190
|
}
|
|
175
191
|
// 置空当前鼠标上面的对象
|
|
@@ -192,7 +208,7 @@ export default class ThreeMouse {
|
|
|
192
208
|
offsetX: this._mousemoveEvent.offsetX,
|
|
193
209
|
offsetY: this._mousemoveEvent.offsetY,
|
|
194
210
|
x: this._mousemoveEvent.x,
|
|
195
|
-
y: this._mousemoveEvent.y
|
|
211
|
+
y: this._mousemoveEvent.y,
|
|
196
212
|
});
|
|
197
213
|
}
|
|
198
214
|
// 置空当前鼠标上面的对象
|
|
@@ -203,12 +219,15 @@ export default class ThreeMouse {
|
|
|
203
219
|
_mousemove = (e) => {
|
|
204
220
|
this._mousemoveEvent = e;
|
|
205
221
|
this._frame = this._renderer.info.render.frame;
|
|
206
|
-
if (document.pointerLockElement) {
|
|
222
|
+
if (document.pointerLockElement) {
|
|
223
|
+
// 如果当前有元素 锁住了鼠标
|
|
207
224
|
this._mosePosition.set(0, 0); // 鼠标就指向canvas 的正中心
|
|
208
225
|
}
|
|
209
226
|
else {
|
|
210
|
-
this._mosePosition.x =
|
|
211
|
-
|
|
227
|
+
this._mosePosition.x =
|
|
228
|
+
(e.offsetX / this._renderer.domElement.offsetWidth) * 2 - 1;
|
|
229
|
+
this._mosePosition.y =
|
|
230
|
+
-(e.offsetY / this._renderer.domElement.offsetHeight) * 2 + 1;
|
|
212
231
|
}
|
|
213
232
|
this._raycaster.setFromCamera(this._mosePosition, this._camera); // 设置射线拾取的参数
|
|
214
233
|
};
|
|
@@ -235,7 +254,7 @@ export default class ThreeMouse {
|
|
|
235
254
|
offsetX: this._mousemoveEvent.offsetX,
|
|
236
255
|
offsetY: this._mousemoveEvent.offsetY,
|
|
237
256
|
x: this._mousemoveEvent.x,
|
|
238
|
-
y: this._mousemoveEvent.y
|
|
257
|
+
y: this._mousemoveEvent.y,
|
|
239
258
|
});
|
|
240
259
|
}
|
|
241
260
|
};
|
|
@@ -260,7 +279,7 @@ export default class ThreeMouse {
|
|
|
260
279
|
offsetX: this._mousemoveEvent.offsetX,
|
|
261
280
|
offsetY: this._mousemoveEvent.offsetY,
|
|
262
281
|
x: this._mousemoveEvent.x,
|
|
263
|
-
y: this._mousemoveEvent.y
|
|
282
|
+
y: this._mousemoveEvent.y,
|
|
264
283
|
});
|
|
265
284
|
}
|
|
266
285
|
// 触发鼠标弹起事件
|
|
@@ -271,7 +290,7 @@ export default class ThreeMouse {
|
|
|
271
290
|
// 是否有双击事件
|
|
272
291
|
if (this.hasEvent(this._mesh_Down, ["dbclick"])) {
|
|
273
292
|
this._click_num++;
|
|
274
|
-
await new Promise(resolve => setTimeout(resolve, 200));
|
|
293
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
275
294
|
// 只点击了一次
|
|
276
295
|
if (this._click_num === 1) {
|
|
277
296
|
if (this.hasEvent(this._mesh_Down, ["click"])) {
|
|
@@ -285,10 +304,10 @@ export default class ThreeMouse {
|
|
|
285
304
|
offsetX: this._mousemoveEvent.offsetX,
|
|
286
305
|
offsetY: this._mousemoveEvent.offsetY,
|
|
287
306
|
x: this._mousemoveEvent.x,
|
|
288
|
-
y: this._mousemoveEvent.y
|
|
307
|
+
y: this._mousemoveEvent.y,
|
|
289
308
|
});
|
|
290
309
|
}
|
|
291
|
-
if (this.hasEvent(this._mesh_Down, ["leftclick"]) &&
|
|
310
|
+
if (this.hasEvent(this._mesh_Down, ["leftclick"]) && e.button === 0) {
|
|
292
311
|
this._mesh_Down.dispatchEvent({
|
|
293
312
|
e: this._mouseEvent,
|
|
294
313
|
...intersection,
|
|
@@ -299,10 +318,11 @@ export default class ThreeMouse {
|
|
|
299
318
|
offsetX: this._mousemoveEvent.offsetX,
|
|
300
319
|
offsetY: this._mousemoveEvent.offsetY,
|
|
301
320
|
x: this._mousemoveEvent.x,
|
|
302
|
-
y: this._mousemoveEvent.y
|
|
321
|
+
y: this._mousemoveEvent.y,
|
|
303
322
|
});
|
|
304
323
|
}
|
|
305
|
-
if (this.hasEvent(this._mesh_Down, ["rightclick"]) &&
|
|
324
|
+
if (this.hasEvent(this._mesh_Down, ["rightclick"]) &&
|
|
325
|
+
e.button === 2) {
|
|
306
326
|
this._mesh_Down.dispatchEvent({
|
|
307
327
|
e: this._mouseEvent,
|
|
308
328
|
...intersection,
|
|
@@ -313,12 +333,14 @@ export default class ThreeMouse {
|
|
|
313
333
|
offsetX: this._mousemoveEvent.offsetX,
|
|
314
334
|
offsetY: this._mousemoveEvent.offsetY,
|
|
315
335
|
x: this._mousemoveEvent.x,
|
|
316
|
-
y: this._mousemoveEvent.y
|
|
336
|
+
y: this._mousemoveEvent.y,
|
|
317
337
|
});
|
|
318
338
|
}
|
|
319
339
|
}
|
|
320
340
|
else if (this._click_num > 1) {
|
|
321
|
-
if (this.hasEvent(this._mesh_Down, ["dbclick"]) &&
|
|
341
|
+
if (this.hasEvent(this._mesh_Down, ["dbclick"]) &&
|
|
342
|
+
new Date().valueOf() - this._click_num > 1 &&
|
|
343
|
+
e.button === 0) {
|
|
322
344
|
this._mesh_Down.dispatchEvent({
|
|
323
345
|
e: this._mouseEvent,
|
|
324
346
|
...intersection,
|
|
@@ -329,7 +351,7 @@ export default class ThreeMouse {
|
|
|
329
351
|
offsetX: this._mousemoveEvent.offsetX,
|
|
330
352
|
offsetY: this._mousemoveEvent.offsetY,
|
|
331
353
|
x: this._mousemoveEvent.x,
|
|
332
|
-
y: this._mousemoveEvent.y
|
|
354
|
+
y: this._mousemoveEvent.y,
|
|
333
355
|
});
|
|
334
356
|
}
|
|
335
357
|
}
|
|
@@ -346,10 +368,10 @@ export default class ThreeMouse {
|
|
|
346
368
|
offsetX: this._mousemoveEvent.offsetX,
|
|
347
369
|
offsetY: this._mousemoveEvent.offsetY,
|
|
348
370
|
x: this._mousemoveEvent.x,
|
|
349
|
-
y: this._mousemoveEvent.y
|
|
371
|
+
y: this._mousemoveEvent.y,
|
|
350
372
|
});
|
|
351
373
|
}
|
|
352
|
-
if (this.hasEvent(this._mesh_Down, ["leftclick"]) &&
|
|
374
|
+
if (this.hasEvent(this._mesh_Down, ["leftclick"]) && e.button === 0) {
|
|
353
375
|
this._mesh_Down.dispatchEvent({
|
|
354
376
|
e: this._mouseEvent,
|
|
355
377
|
...intersection,
|
|
@@ -360,10 +382,10 @@ export default class ThreeMouse {
|
|
|
360
382
|
offsetX: this._mousemoveEvent.offsetX,
|
|
361
383
|
offsetY: this._mousemoveEvent.offsetY,
|
|
362
384
|
x: this._mousemoveEvent.x,
|
|
363
|
-
y: this._mousemoveEvent.y
|
|
385
|
+
y: this._mousemoveEvent.y,
|
|
364
386
|
});
|
|
365
387
|
}
|
|
366
|
-
if (this.hasEvent(this._mesh_Down, ["rightclick"]) &&
|
|
388
|
+
if (this.hasEvent(this._mesh_Down, ["rightclick"]) && e.button === 2) {
|
|
367
389
|
this._mesh_Down.dispatchEvent({
|
|
368
390
|
e: this._mouseEvent,
|
|
369
391
|
...intersection,
|
|
@@ -374,7 +396,7 @@ export default class ThreeMouse {
|
|
|
374
396
|
offsetX: this._mousemoveEvent.offsetX,
|
|
375
397
|
offsetY: this._mousemoveEvent.offsetY,
|
|
376
398
|
x: this._mousemoveEvent.x,
|
|
377
|
-
y: this._mousemoveEvent.y
|
|
399
|
+
y: this._mousemoveEvent.y,
|
|
378
400
|
});
|
|
379
401
|
}
|
|
380
402
|
}
|
package/package.json
CHANGED
package/pass/glow_pass.js
CHANGED
|
@@ -556,14 +556,12 @@ export default function glow_pass(renderer, camera, object3d, baseDepthTexture)
|
|
|
556
556
|
blurShader.uniforms.tDiffuse.value = blur1TextureTarget.texture;
|
|
557
557
|
blurShader.uniforms.opacity.value = 0.1;
|
|
558
558
|
fsQuad.render(renderer, blurShader);
|
|
559
|
-
//最后抗锯齿
|
|
560
559
|
renderer.setRenderTarget(blur1TextureTarget);
|
|
561
|
-
|
|
562
|
-
fsQuad.render(renderer,
|
|
560
|
+
copyShader.uniforms.map.value = blur2TextureTarget.texture;
|
|
561
|
+
fsQuad.render(renderer, copyShader);
|
|
563
562
|
// 还原帧缓冲区 减去原始纹理保留描边
|
|
564
563
|
renderer.setRenderTarget(originRenderTarget);
|
|
565
|
-
filterSelectShader.uniforms.selectTexture.value =
|
|
566
|
-
selectDethpTestTextureTarget.texture;
|
|
564
|
+
filterSelectShader.uniforms.selectTexture.value = selectDethpTestTextureTarget.texture;
|
|
567
565
|
filterSelectShader.uniforms.blurTexture.value = blur1TextureTarget.texture;
|
|
568
566
|
filterSelectShader.uniforms.opacity.value = glow_opacity;
|
|
569
567
|
filterSelectShader.blending = NormalBlending; // 与有的纹理融合计算 保留前面通道传递下来的纹理
|
package/pass/stroke_pass.js
CHANGED
|
@@ -314,7 +314,7 @@ const FXAAShaderMaterial = new ShaderMaterial({
|
|
|
314
314
|
transparent: true
|
|
315
315
|
});
|
|
316
316
|
// 描边着色器
|
|
317
|
-
const
|
|
317
|
+
const strokeShader = new RawShaderMaterial({
|
|
318
318
|
uniforms: {
|
|
319
319
|
tDiffuse: { value: null },
|
|
320
320
|
color: { value: new Color("#0f0") },
|
|
@@ -483,12 +483,12 @@ export default function stroke_pass(renderer, camera, object3d, baseDepthTexture
|
|
|
483
483
|
renderer.clear();
|
|
484
484
|
renderer.render(scene, camera);
|
|
485
485
|
// 设置描边着色器的分辨率
|
|
486
|
-
|
|
486
|
+
strokeShader.uniforms.resolution.value.set(1 / size.x, 1 / size.y);
|
|
487
487
|
// 设置抗锯齿着色器的分辨率
|
|
488
488
|
FXAAShaderMaterial.uniforms.resolution.value.set(1 / size.x, 1 / size.y);
|
|
489
489
|
//描边颜色
|
|
490
|
-
|
|
491
|
-
|
|
490
|
+
strokeShader.uniforms.color.value.set(stroke_color);
|
|
491
|
+
strokeShader.uniforms.width.value = 1;
|
|
492
492
|
//深度测试
|
|
493
493
|
renderer.setRenderTarget(selectDethpTestTextureTarget);
|
|
494
494
|
renderer.clear();
|
|
@@ -498,26 +498,25 @@ export default function stroke_pass(renderer, camera, object3d, baseDepthTexture
|
|
|
498
498
|
fsQuad.render(renderer, depthTestShader);
|
|
499
499
|
//一次描边
|
|
500
500
|
renderer.setRenderTarget(blur1TextureTarget);
|
|
501
|
-
|
|
502
|
-
fsQuad.render(renderer,
|
|
501
|
+
strokeShader.uniforms.tDiffuse.value = selectDethpTestTextureTarget.texture;
|
|
502
|
+
fsQuad.render(renderer, strokeShader);
|
|
503
503
|
//二次描边
|
|
504
504
|
renderer.setRenderTarget(blur2TextureTarget);
|
|
505
|
-
|
|
506
|
-
fsQuad.render(renderer,
|
|
505
|
+
strokeShader.uniforms.tDiffuse.value = blur1TextureTarget.texture;
|
|
506
|
+
fsQuad.render(renderer, strokeShader);
|
|
507
507
|
for (let i = 0; i < stroke_width - 2; i++) {
|
|
508
508
|
//一次描边
|
|
509
509
|
renderer.setRenderTarget(blur1TextureTarget);
|
|
510
|
-
|
|
511
|
-
fsQuad.render(renderer,
|
|
510
|
+
strokeShader.uniforms.tDiffuse.value = blur2TextureTarget.texture;
|
|
511
|
+
fsQuad.render(renderer, strokeShader);
|
|
512
512
|
//二次描边
|
|
513
513
|
renderer.setRenderTarget(blur2TextureTarget);
|
|
514
|
-
|
|
515
|
-
fsQuad.render(renderer,
|
|
514
|
+
strokeShader.uniforms.tDiffuse.value = blur1TextureTarget.texture;
|
|
515
|
+
fsQuad.render(renderer, strokeShader);
|
|
516
516
|
}
|
|
517
|
-
//最后抗锯齿
|
|
518
517
|
renderer.setRenderTarget(blur1TextureTarget);
|
|
519
|
-
|
|
520
|
-
fsQuad.render(renderer,
|
|
518
|
+
copyShader.uniforms.map.value = blur2TextureTarget.texture;
|
|
519
|
+
fsQuad.render(renderer, copyShader);
|
|
521
520
|
// 还原帧缓冲区 减去原始纹理保留描边
|
|
522
521
|
renderer.setRenderTarget(originRenderTarget);
|
|
523
522
|
filterSelectShader.uniforms.selectTexture.value = selectDethpTestTextureTarget.texture;
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { ShaderMaterial, Vector2, ShaderChunk, NoBlending } from "three";
|
|
2
|
+
// 渲染目标绘制到渲染器着色器
|
|
3
|
+
export const baseTextureToRenderShader = new ShaderMaterial({
|
|
4
|
+
uniforms: {
|
|
5
|
+
tDiffuse: { value: null },
|
|
6
|
+
resolution: { value: new Vector2(1 / 1024, 1 / 1024) }
|
|
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
|
+
precision highp float;
|
|
21
|
+
|
|
22
|
+
uniform sampler2D tDiffuse;
|
|
23
|
+
|
|
24
|
+
uniform vec2 resolution;
|
|
25
|
+
|
|
26
|
+
varying vec2 vUv;
|
|
27
|
+
|
|
28
|
+
#ifndef FXAA_DISCARD
|
|
29
|
+
//
|
|
30
|
+
// Only valid for PC OpenGL currently.
|
|
31
|
+
// Probably will not work when FXAA_GREEN_AS_LUMA = 1.
|
|
32
|
+
//
|
|
33
|
+
// 1 = Use discard on pixels which don't need AA.
|
|
34
|
+
// For APIs which enable concurrent TEX+ROP from same surface.
|
|
35
|
+
// 0 = Return unchanged color on pixels which don't need AA.
|
|
36
|
+
//
|
|
37
|
+
#define FXAA_DISCARD 0
|
|
38
|
+
#endif
|
|
39
|
+
|
|
40
|
+
/*--------------------------------------------------------------------------*/
|
|
41
|
+
#define FxaaTexTop(t, p) texture2D(t, p, -100.0)
|
|
42
|
+
#define FxaaTexOff(t, p, o, r) texture2D(t, p + (o * r), -100.0)
|
|
43
|
+
/*--------------------------------------------------------------------------*/
|
|
44
|
+
|
|
45
|
+
#define NUM_SAMPLES 5
|
|
46
|
+
|
|
47
|
+
// assumes colors have premultipliedAlpha, so that the calculated color contrast is scaled by alpha
|
|
48
|
+
float contrast( vec4 a, vec4 b ) {
|
|
49
|
+
vec4 diff = abs( a - b );
|
|
50
|
+
return max( max( max( diff.r, diff.g ), diff.b ), diff.a );
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/*============================================================================
|
|
54
|
+
|
|
55
|
+
FXAA3 QUALITY - PC
|
|
56
|
+
|
|
57
|
+
============================================================================*/
|
|
58
|
+
|
|
59
|
+
/*--------------------------------------------------------------------------*/
|
|
60
|
+
vec4 FxaaPixelShader(
|
|
61
|
+
vec2 posM,
|
|
62
|
+
sampler2D tex,
|
|
63
|
+
vec2 fxaaQualityRcpFrame,
|
|
64
|
+
float fxaaQualityEdgeThreshold,
|
|
65
|
+
float fxaaQualityinvEdgeThreshold
|
|
66
|
+
) {
|
|
67
|
+
vec4 rgbaM = FxaaTexTop(tex, posM);
|
|
68
|
+
vec4 rgbaS = FxaaTexOff(tex, posM, vec2( 0.0, 1.0), fxaaQualityRcpFrame.xy);
|
|
69
|
+
vec4 rgbaE = FxaaTexOff(tex, posM, vec2( 1.0, 0.0), fxaaQualityRcpFrame.xy);
|
|
70
|
+
vec4 rgbaN = FxaaTexOff(tex, posM, vec2( 0.0,-1.0), fxaaQualityRcpFrame.xy);
|
|
71
|
+
vec4 rgbaW = FxaaTexOff(tex, posM, vec2(-1.0, 0.0), fxaaQualityRcpFrame.xy);
|
|
72
|
+
// . S .
|
|
73
|
+
// W M E
|
|
74
|
+
// . N .
|
|
75
|
+
|
|
76
|
+
bool earlyExit = max( max( max(
|
|
77
|
+
contrast( rgbaM, rgbaN ),
|
|
78
|
+
contrast( rgbaM, rgbaS ) ),
|
|
79
|
+
contrast( rgbaM, rgbaE ) ),
|
|
80
|
+
contrast( rgbaM, rgbaW ) )
|
|
81
|
+
< fxaaQualityEdgeThreshold;
|
|
82
|
+
// . 0 .
|
|
83
|
+
// 0 0 0
|
|
84
|
+
// . 0 .
|
|
85
|
+
|
|
86
|
+
#if (FXAA_DISCARD == 1)
|
|
87
|
+
if(earlyExit) FxaaDiscard;
|
|
88
|
+
#else
|
|
89
|
+
if(earlyExit) return rgbaM;
|
|
90
|
+
#endif
|
|
91
|
+
|
|
92
|
+
float contrastN = contrast( rgbaM, rgbaN );
|
|
93
|
+
float contrastS = contrast( rgbaM, rgbaS );
|
|
94
|
+
float contrastE = contrast( rgbaM, rgbaE );
|
|
95
|
+
float contrastW = contrast( rgbaM, rgbaW );
|
|
96
|
+
|
|
97
|
+
float relativeVContrast = ( contrastN + contrastS ) - ( contrastE + contrastW );
|
|
98
|
+
relativeVContrast *= fxaaQualityinvEdgeThreshold;
|
|
99
|
+
|
|
100
|
+
bool horzSpan = relativeVContrast > 0.;
|
|
101
|
+
// . 1 .
|
|
102
|
+
// 0 0 0
|
|
103
|
+
// . 1 .
|
|
104
|
+
|
|
105
|
+
// 45 deg edge detection and corners of objects, aka V/H contrast is too similar
|
|
106
|
+
if( abs( relativeVContrast ) < .3 ) {
|
|
107
|
+
// locate the edge
|
|
108
|
+
vec2 dirToEdge;
|
|
109
|
+
dirToEdge.x = contrastE > contrastW ? 1. : -1.;
|
|
110
|
+
dirToEdge.y = contrastS > contrastN ? 1. : -1.;
|
|
111
|
+
// . 2 . . 1 .
|
|
112
|
+
// 1 0 2 ~= 0 0 1
|
|
113
|
+
// . 1 . . 0 .
|
|
114
|
+
|
|
115
|
+
// tap 2 pixels and see which ones are "outside" the edge, to
|
|
116
|
+
// determine if the edge is vertical or horizontal
|
|
117
|
+
|
|
118
|
+
vec4 rgbaAlongH = FxaaTexOff(tex, posM, vec2( dirToEdge.x, -dirToEdge.y ), fxaaQualityRcpFrame.xy);
|
|
119
|
+
float matchAlongH = contrast( rgbaM, rgbaAlongH );
|
|
120
|
+
// . 1 .
|
|
121
|
+
// 0 0 1
|
|
122
|
+
// . 0 H
|
|
123
|
+
|
|
124
|
+
vec4 rgbaAlongV = FxaaTexOff(tex, posM, vec2( -dirToEdge.x, dirToEdge.y ), fxaaQualityRcpFrame.xy);
|
|
125
|
+
float matchAlongV = contrast( rgbaM, rgbaAlongV );
|
|
126
|
+
// V 1 .
|
|
127
|
+
// 0 0 1
|
|
128
|
+
// . 0 .
|
|
129
|
+
|
|
130
|
+
relativeVContrast = matchAlongV - matchAlongH;
|
|
131
|
+
relativeVContrast *= fxaaQualityinvEdgeThreshold;
|
|
132
|
+
|
|
133
|
+
if( abs( relativeVContrast ) < .3 ) { // 45 deg edge
|
|
134
|
+
// 1 1 .
|
|
135
|
+
// 0 0 1
|
|
136
|
+
// . 0 1
|
|
137
|
+
|
|
138
|
+
// do a simple blur
|
|
139
|
+
return mix(
|
|
140
|
+
rgbaM,
|
|
141
|
+
(rgbaN + rgbaS + rgbaE + rgbaW) * .25,
|
|
142
|
+
.4
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
horzSpan = relativeVContrast > 0.;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if(!horzSpan) rgbaN = rgbaW;
|
|
150
|
+
if(!horzSpan) rgbaS = rgbaE;
|
|
151
|
+
// . 0 . 1
|
|
152
|
+
// 1 0 1 -> 0
|
|
153
|
+
// . 0 . 1
|
|
154
|
+
|
|
155
|
+
bool pairN = contrast( rgbaM, rgbaN ) > contrast( rgbaM, rgbaS );
|
|
156
|
+
if(!pairN) rgbaN = rgbaS;
|
|
157
|
+
|
|
158
|
+
vec2 offNP;
|
|
159
|
+
offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
|
|
160
|
+
offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
|
|
161
|
+
|
|
162
|
+
bool doneN = false;
|
|
163
|
+
bool doneP = false;
|
|
164
|
+
|
|
165
|
+
float nDist = 0.;
|
|
166
|
+
float pDist = 0.;
|
|
167
|
+
|
|
168
|
+
vec2 posN = posM;
|
|
169
|
+
vec2 posP = posM;
|
|
170
|
+
|
|
171
|
+
int iterationsUsed = 0;
|
|
172
|
+
int iterationsUsedN = 0;
|
|
173
|
+
int iterationsUsedP = 0;
|
|
174
|
+
for( int i = 0; i < NUM_SAMPLES; i++ ) {
|
|
175
|
+
iterationsUsed = i;
|
|
176
|
+
|
|
177
|
+
float increment = float(i + 1);
|
|
178
|
+
|
|
179
|
+
if(!doneN) {
|
|
180
|
+
nDist += increment;
|
|
181
|
+
posN = posM + offNP * nDist;
|
|
182
|
+
vec4 rgbaEndN = FxaaTexTop(tex, posN.xy);
|
|
183
|
+
doneN = contrast( rgbaEndN, rgbaM ) > contrast( rgbaEndN, rgbaN );
|
|
184
|
+
iterationsUsedN = i;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if(!doneP) {
|
|
188
|
+
pDist += increment;
|
|
189
|
+
posP = posM - offNP * pDist;
|
|
190
|
+
vec4 rgbaEndP = FxaaTexTop(tex, posP.xy);
|
|
191
|
+
doneP = contrast( rgbaEndP, rgbaM ) > contrast( rgbaEndP, rgbaN );
|
|
192
|
+
iterationsUsedP = i;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if(doneN || doneP) break;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
if ( !doneP && !doneN ) return rgbaM; // failed to find end of edge
|
|
200
|
+
|
|
201
|
+
float dist = min(
|
|
202
|
+
doneN ? float( iterationsUsedN ) / float( NUM_SAMPLES - 1 ) : 1.,
|
|
203
|
+
doneP ? float( iterationsUsedP ) / float( NUM_SAMPLES - 1 ) : 1.
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
// hacky way of reduces blurriness of mostly diagonal edges
|
|
207
|
+
// but reduces AA quality
|
|
208
|
+
dist = pow(dist, .5);
|
|
209
|
+
|
|
210
|
+
dist = 1. - dist;
|
|
211
|
+
|
|
212
|
+
return mix(
|
|
213
|
+
rgbaM,
|
|
214
|
+
rgbaN,
|
|
215
|
+
dist * .5
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
void main() {
|
|
220
|
+
const float edgeDetectionQuality = .2;
|
|
221
|
+
const float invEdgeDetectionQuality = 1. / edgeDetectionQuality;
|
|
222
|
+
|
|
223
|
+
gl_FragColor = sRGBTransferOETF(FxaaPixelShader(
|
|
224
|
+
vUv,
|
|
225
|
+
tDiffuse,
|
|
226
|
+
resolution,
|
|
227
|
+
edgeDetectionQuality, // [0,1] contrast needed, otherwise early discard
|
|
228
|
+
invEdgeDetectionQuality
|
|
229
|
+
));
|
|
230
|
+
${ShaderChunk.logdepthbuf_fragment}
|
|
231
|
+
}
|
|
232
|
+
`,
|
|
233
|
+
blending: NoBlending,
|
|
234
|
+
depthTest: false,
|
|
235
|
+
depthWrite: false,
|
|
236
|
+
transparent: true
|
|
237
|
+
});
|
package/shaders.d.ts
CHANGED
|
@@ -5,6 +5,3 @@ export declare const orthographicCamera: OrthographicCamera;
|
|
|
5
5
|
export declare const clearShader: ShaderMaterial;
|
|
6
6
|
export declare const intersectionShader: ShaderMaterial;
|
|
7
7
|
export declare const copyShader: ShaderMaterial;
|
|
8
|
-
export declare const baseTextureToRenderShader: ShaderMaterial;
|
|
9
|
-
export declare const strokeShader: ShaderMaterial;
|
|
10
|
-
export declare const gaussBlurShader: ShaderMaterial;
|
package/shaders.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @Last Modified by: xiaosihan
|
|
5
5
|
* @Last Modified time: 2022-04-02 18:28:38
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { NoBlending, OrthographicCamera, ShaderChunk, ShaderMaterial } from "three";
|
|
8
8
|
import FullScreenQuad from "./pass/FullScreenQuad";
|
|
9
9
|
// 常用着色器及工具
|
|
10
10
|
// 全屏渲染模型
|
|
@@ -95,163 +95,3 @@ export const copyShader = new ShaderMaterial({
|
|
|
95
95
|
depthWrite: true,
|
|
96
96
|
transparent: true,
|
|
97
97
|
});
|
|
98
|
-
// 渲染目标绘制到渲染器着色器
|
|
99
|
-
export const baseTextureToRenderShader = new ShaderMaterial({
|
|
100
|
-
uniforms: {
|
|
101
|
-
map: { value: null },
|
|
102
|
-
opacity: { value: 1.0 }, // 透明度
|
|
103
|
-
},
|
|
104
|
-
vertexShader: `
|
|
105
|
-
${ShaderChunk.common}
|
|
106
|
-
${ShaderChunk.logdepthbuf_pars_vertex}
|
|
107
|
-
varying vec2 vUv;
|
|
108
|
-
void main() {
|
|
109
|
-
vUv = uv;
|
|
110
|
-
gl_Position = vec4(position, 1.0);
|
|
111
|
-
${ShaderChunk.logdepthbuf_vertex}
|
|
112
|
-
}
|
|
113
|
-
`,
|
|
114
|
-
fragmentShader: `
|
|
115
|
-
${ShaderChunk.logdepthbuf_pars_fragment}
|
|
116
|
-
uniform sampler2D map;
|
|
117
|
-
uniform float opacity;
|
|
118
|
-
varying vec2 vUv;
|
|
119
|
-
void main() {
|
|
120
|
-
gl_FragColor = sRGBTransferOETF(texture(map, vUv));
|
|
121
|
-
${ShaderChunk.logdepthbuf_fragment}
|
|
122
|
-
}
|
|
123
|
-
`,
|
|
124
|
-
depthTest: true,
|
|
125
|
-
depthWrite: true,
|
|
126
|
-
transparent: true,
|
|
127
|
-
});
|
|
128
|
-
// 描边着色器
|
|
129
|
-
export const strokeShader = new ShaderMaterial({
|
|
130
|
-
uniforms: {
|
|
131
|
-
map: { value: null },
|
|
132
|
-
resolution: { value: new Vector2(512, 512) },
|
|
133
|
-
strokeWidth: { value: 1.0 },
|
|
134
|
-
strokeColor: { value: new Color("#B2F2FF") },
|
|
135
|
-
opacity: { value: 1.0 }, // 透明度
|
|
136
|
-
},
|
|
137
|
-
vertexShader: `
|
|
138
|
-
varying vec2 vUv;
|
|
139
|
-
void main() {
|
|
140
|
-
vUv = uv;
|
|
141
|
-
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
142
|
-
}
|
|
143
|
-
`,
|
|
144
|
-
fragmentShader: `
|
|
145
|
-
uniform sampler2D map;
|
|
146
|
-
uniform vec2 resolution;
|
|
147
|
-
uniform vec3 strokeColor; // 描边颜色
|
|
148
|
-
uniform float strokeWidth; // 描边厚度
|
|
149
|
-
uniform float opacity; // 透明度
|
|
150
|
-
|
|
151
|
-
varying vec2 vUv;
|
|
152
|
-
|
|
153
|
-
// 获取当前叠加vu坐标偏移量的颜色值
|
|
154
|
-
vec4 offsetColor(vec2 vu){
|
|
155
|
-
return texture2D(map, vUv + (vu * (strokeWidth / resolution) ) );
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
vec4 fragColor(){
|
|
159
|
-
|
|
160
|
-
vec4 currentColor = offsetColor(vec2(0.0, 0.0));
|
|
161
|
-
|
|
162
|
-
if(
|
|
163
|
-
currentColor.a < min(0.2, opacity) && (
|
|
164
|
-
offsetColor(vec2(0.0, 1.0)).a > 0.0 ||
|
|
165
|
-
offsetColor(vec2(0.0, -1.0)).a > 0.0 ||
|
|
166
|
-
offsetColor(vec2(1.0, 0.0)).a > 0.0 ||
|
|
167
|
-
offsetColor(vec2(-1.0, 0.0)).a > 0.0 ||
|
|
168
|
-
|
|
169
|
-
offsetColor(vec2(1.0) * 0.7).a > 0.0 ||
|
|
170
|
-
offsetColor(vec2(-1.0) * 0.7).a > 0.0 ||
|
|
171
|
-
offsetColor(vec2(-1.0, 1.0) * 0.7).a > 0.0 ||
|
|
172
|
-
offsetColor(vec2(1.0, -1.0) * 0.7).a > 0.0
|
|
173
|
-
)
|
|
174
|
-
){
|
|
175
|
-
return vec4( strokeColor, opacity);
|
|
176
|
-
}else{
|
|
177
|
-
// discard;
|
|
178
|
-
return offsetColor(vec2(0.0, 0.0));
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
void main() {
|
|
184
|
-
gl_FragColor = fragColor();
|
|
185
|
-
}
|
|
186
|
-
`,
|
|
187
|
-
blending: NoBlending,
|
|
188
|
-
depthTest: true,
|
|
189
|
-
depthWrite: true,
|
|
190
|
-
transparent: true,
|
|
191
|
-
});
|
|
192
|
-
// 高斯模糊着色器 让颜色过渡更自然
|
|
193
|
-
export const gaussBlurShader = new ShaderMaterial({
|
|
194
|
-
uniforms: {
|
|
195
|
-
map: { value: null },
|
|
196
|
-
opacity: { value: 1.0 },
|
|
197
|
-
radius: { value: 3.0 },
|
|
198
|
-
resolution: { value: new Vector2(512, 512) }, // 渲染器的分辨率
|
|
199
|
-
},
|
|
200
|
-
vertexShader: `
|
|
201
|
-
varying vec2 vUv;
|
|
202
|
-
void main() {
|
|
203
|
-
vUv = uv;
|
|
204
|
-
gl_Position = vec4(position, 1.0);
|
|
205
|
-
}
|
|
206
|
-
`,
|
|
207
|
-
fragmentShader: `
|
|
208
|
-
uniform sampler2D map;
|
|
209
|
-
uniform float opacity;
|
|
210
|
-
uniform vec2 resolution;
|
|
211
|
-
uniform float radius;
|
|
212
|
-
varying vec2 vUv;
|
|
213
|
-
|
|
214
|
-
vec4 offsetColor( vec2 uv){
|
|
215
|
-
return texture2D(map, vUv + (uv / resolution * radius) );
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
vec4 blurColor(){
|
|
219
|
-
|
|
220
|
-
vec4 leftColor = offsetColor( vec2(-1.0, 0.0) );
|
|
221
|
-
|
|
222
|
-
vec4 rightColor = offsetColor( vec2(1.0, 0.0) );
|
|
223
|
-
|
|
224
|
-
// 左右颜色混合
|
|
225
|
-
vec4 leftRightColor = vec4(
|
|
226
|
-
mix( leftColor.rgb ,rightColor.rgb, rightColor.a / (leftColor.a + rightColor.a)),
|
|
227
|
-
(leftColor.a + rightColor.a) / 2.0
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
vec4 downColor = offsetColor( vec2(0.0, -1.0));
|
|
231
|
-
|
|
232
|
-
vec4 upColor = offsetColor( vec2(0.0, 1.0));
|
|
233
|
-
|
|
234
|
-
// 上下颜色混合
|
|
235
|
-
vec4 upDownColor = vec4(
|
|
236
|
-
mix( downColor.rgb, upColor.rgb, upColor.a / (downColor.a + upColor.a) ),
|
|
237
|
-
(downColor.a + upColor.a) / 2.0
|
|
238
|
-
);
|
|
239
|
-
|
|
240
|
-
vec4 color = vec4(
|
|
241
|
-
mix( leftRightColor.rgb, upDownColor.rgb, upDownColor.a / (leftRightColor.a + upDownColor.a) ),
|
|
242
|
-
(leftRightColor.a + upDownColor.a) / 2.0
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
return color;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
void main() {
|
|
249
|
-
gl_FragColor = blurColor();
|
|
250
|
-
gl_FragColor.a *= opacity;
|
|
251
|
-
}
|
|
252
|
-
`,
|
|
253
|
-
blending: NoBlending,
|
|
254
|
-
depthTest: false,
|
|
255
|
-
depthWrite: false,
|
|
256
|
-
transparent: true,
|
|
257
|
-
});
|