three-base 2.0.22 → 2.0.24
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.js +1 -2
- package/Mirror.ts +1 -2
- package/README.md +1 -0
- package/ThreeBase.d.ts +2 -0
- package/ThreeBase.js +48 -26
- package/ThreeBase.ts +59 -32
- package/package.json +1 -1
- package/pass/glow_pass.js +1 -1
- package/pass/glow_pass.ts +1 -1
- package/pass/stroke_pass.js +1 -1
- package/pass/stroke_pass.ts +1 -1
- package/shaders/FXAAShaderMaterial.d.ts +3 -0
- package/shaders/FXAAShaderMaterial.js +244 -0
- package/shaders/FXAAShaderMaterial.ts +248 -0
package/Mirror.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author: xiaosihan
|
|
3
3
|
* @Date: 2023-08-04 17:17:15
|
|
4
4
|
* @Last Modified by: xiaosihan
|
|
5
|
-
* @Last Modified time:
|
|
5
|
+
* @Last Modified time: 2024-01-20 05:33:51
|
|
6
6
|
*/
|
|
7
7
|
import { Color, DoubleSide, HalfFloatType, Matrix4, Mesh, PerspectiveCamera, Plane, PlaneGeometry, ShaderMaterial, Vector3, Vector4, WebGLRenderTarget } from "three";
|
|
8
8
|
// 镜子模型
|
|
@@ -180,7 +180,6 @@ export default class Mirror extends Mesh {
|
|
|
180
180
|
//@ts-ignore
|
|
181
181
|
const viewport = this.camera.viewport;
|
|
182
182
|
if (viewport !== undefined) {
|
|
183
|
-
debugger;
|
|
184
183
|
renderer.state.viewport(viewport);
|
|
185
184
|
}
|
|
186
185
|
this.visible = true;
|
package/Mirror.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author: xiaosihan
|
|
3
3
|
* @Date: 2023-08-04 17:17:15
|
|
4
4
|
* @Last Modified by: xiaosihan
|
|
5
|
-
* @Last Modified time:
|
|
5
|
+
* @Last Modified time: 2024-01-20 05:33:51
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { BufferGeometry, Camera, Color, DoubleSide, Group, HalfFloatType, Material, Matrix4, Mesh, PerspectiveCamera, Plane, PlaneGeometry, Scene, ShaderMaterial, Vector3, Vector4, WebGLRenderTarget, WebGLRenderer } from "three";
|
|
@@ -233,7 +233,6 @@ export default class Mirror extends Mesh {
|
|
|
233
233
|
//@ts-ignore
|
|
234
234
|
const viewport = this.camera.viewport;
|
|
235
235
|
if (viewport !== undefined) {
|
|
236
|
-
debugger;
|
|
237
236
|
renderer.state.viewport(viewport);
|
|
238
237
|
}
|
|
239
238
|
|
package/README.md
CHANGED
package/ThreeBase.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
23
23
|
controlsPosition: Transition;
|
|
24
24
|
gridHelper: GridHelper;
|
|
25
25
|
axesHelper: AxesHelper;
|
|
26
|
+
frame: number;
|
|
26
27
|
init(): void;
|
|
27
28
|
resetLookAt({ position, center, }: {
|
|
28
29
|
position: Vector3;
|
|
@@ -45,6 +46,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
45
46
|
autoRender: boolean;
|
|
46
47
|
needRender: boolean;
|
|
47
48
|
stopRender(): void;
|
|
49
|
+
hasStrokeOrPass(): boolean;
|
|
48
50
|
render(): void;
|
|
49
51
|
private renderBindThis;
|
|
50
52
|
download(fileName?: string): void;
|
package/ThreeBase.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* @Author: xiaosihan
|
|
3
3
|
* @Date: 2021-12-20 13:38:22
|
|
4
4
|
* @Last Modified by: xiaosihan
|
|
5
|
-
* @Last Modified time:
|
|
5
|
+
* @Last Modified time: 2024-01-20 05:33:28
|
|
6
6
|
*/
|
|
7
7
|
import { round } from "lodash";
|
|
8
|
-
import { AxesHelper, DepthFormat, DepthTexture, EventDispatcher, GridHelper, LinearFilter, Mesh, MOUSE, NoBlending,
|
|
8
|
+
import { AxesHelper, DepthFormat, DepthTexture, EventDispatcher, GridHelper, LinearFilter, LinearSRGBColorSpace, 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 glow_pass from "./pass/glow_pass";
|
|
@@ -15,6 +15,7 @@ import threeLoader from "./threeLoader";
|
|
|
15
15
|
import ThreeMouse from "./ThreeMouse";
|
|
16
16
|
import threeUtils from "./threeUtils";
|
|
17
17
|
import Transition from "./Transition";
|
|
18
|
+
import FXAAShaderMaterial from "./shaders/FXAAShaderMaterial";
|
|
18
19
|
// three.js 的基础对象
|
|
19
20
|
export default class ThreeBase extends EventDispatcher {
|
|
20
21
|
constructor() {
|
|
@@ -29,7 +30,6 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
29
30
|
baseDepthTexture.anisotropy = 16;
|
|
30
31
|
return baseDepthTexture;
|
|
31
32
|
})();
|
|
32
|
-
// TODO 渲染目标的颜色空间问题 还没有处理好
|
|
33
33
|
// 基础纹理渲染对象
|
|
34
34
|
baseRenderTarget = (() => {
|
|
35
35
|
const baseRenderTarget = new WebGLRenderTarget(128, 128, {
|
|
@@ -64,7 +64,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
64
64
|
});
|
|
65
65
|
renderer.domElement.id = generateUUID();
|
|
66
66
|
renderer.localClippingEnabled = true;
|
|
67
|
-
renderer.outputColorSpace =
|
|
67
|
+
renderer.outputColorSpace = LinearSRGBColorSpace;
|
|
68
68
|
renderer.setPixelRatio(window.devicePixelRatio);
|
|
69
69
|
renderer.autoClear = false;
|
|
70
70
|
renderer.clear();
|
|
@@ -183,6 +183,8 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
183
183
|
}
|
|
184
184
|
return axesHelper;
|
|
185
185
|
})();
|
|
186
|
+
//TODO 设置帧频率 默认50帧
|
|
187
|
+
frame = 50;
|
|
186
188
|
init() {
|
|
187
189
|
// 资源加载进度有更新时, 需要渲染
|
|
188
190
|
threeLoader.addEventListener("progress", () => {
|
|
@@ -238,7 +240,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
238
240
|
return {
|
|
239
241
|
center: new Vector3(...center),
|
|
240
242
|
position: new Vector3(...position),
|
|
241
|
-
centerPosition: `
|
|
243
|
+
centerPosition: `center: new Vector3(${center.join(",")}),position: new Vector3(${position.join(",")})`
|
|
242
244
|
};
|
|
243
245
|
}
|
|
244
246
|
// 三维向量转化成屏幕上的2维向量
|
|
@@ -279,10 +281,21 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
279
281
|
this.setSize(100, 100);
|
|
280
282
|
this.renderer.domElement.style.opacity = "0";
|
|
281
283
|
}
|
|
284
|
+
// 判断是否有 发光和描边的对象 以便判断是否需要 渲染深度纹理
|
|
285
|
+
hasStrokeOrPass() {
|
|
286
|
+
let has_stroke_or_pass = false;
|
|
287
|
+
this.scene.traverse(obj => {
|
|
288
|
+
const { stroke_enable = false, stroke_width = 1, glow_enable = false, glow_width = 1 } = obj.userData;
|
|
289
|
+
if ((stroke_enable && stroke_width > 0) || (glow_enable && glow_width > 0)) {
|
|
290
|
+
has_stroke_or_pass = true;
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
return has_stroke_or_pass;
|
|
294
|
+
}
|
|
282
295
|
// 渲染场景
|
|
283
296
|
render() {
|
|
284
297
|
// 控制器在移动时鼠标不能操作
|
|
285
|
-
|
|
298
|
+
this.renderer.domElement.style.pointerEvents = (!this.controlsPosition.isDone() || !this.controlsCenter.isDone()) ? "none" : "all";
|
|
286
299
|
// canvas 没有在页面上面的话 就跳过渲染
|
|
287
300
|
if (!threeUtils.inDocument(this.renderer.domElement)) {
|
|
288
301
|
this.stopRender();
|
|
@@ -305,23 +318,24 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
305
318
|
}
|
|
306
319
|
// 渲染场景
|
|
307
320
|
this.dispatchEvent({ type: "beforeRender" });
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
321
|
+
const has_stroke_or_pass = this.hasStrokeOrPass();
|
|
322
|
+
if (has_stroke_or_pass) {
|
|
323
|
+
// 把基础场景渲染到 帧缓冲区 在后期通道中会用到
|
|
324
|
+
this.renderer.setRenderTarget(this.baseRenderTarget);
|
|
325
|
+
this.renderer.clear();
|
|
326
|
+
this.renderer.render(this.scene, this.camera);
|
|
327
|
+
this.renderer.setRenderTarget(null);
|
|
328
|
+
}
|
|
312
329
|
// 清空主画布
|
|
313
|
-
this.renderer.setRenderTarget(null);
|
|
314
330
|
this.renderer.clear();
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
glow_pass(this.renderer, this.camera, obj, this.baseDepthTexture);
|
|
324
|
-
});
|
|
331
|
+
this.renderer.render(this.scene, this.camera);
|
|
332
|
+
if (has_stroke_or_pass) {
|
|
333
|
+
// 查找需要绘制描边的对象,并且绘制描边
|
|
334
|
+
this.scene.traverse(obj => {
|
|
335
|
+
stroke_pass(this.renderer, this.camera, obj, this.baseDepthTexture);
|
|
336
|
+
glow_pass(this.renderer, this.camera, obj, this.baseDepthTexture);
|
|
337
|
+
});
|
|
338
|
+
}
|
|
325
339
|
this.dispatchEvent({ type: "afterRender" });
|
|
326
340
|
}
|
|
327
341
|
renderBindThis = this.render.bind(this);
|
|
@@ -445,13 +459,21 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
445
459
|
this.renderTargetgaussBlur(renderTarget, 1, 1);
|
|
446
460
|
this.renderTargetgaussBlur(renderTarget, 1, 1);
|
|
447
461
|
}
|
|
448
|
-
//
|
|
462
|
+
// 需要做康锯齿处理 渲染 渲染目标
|
|
449
463
|
renderRendererTarget(renderTarget, alpha = false) {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
fullScreenMesh.material = coptyShader;
|
|
453
|
-
coptyShader.blending = alpha ? NoBlending : NormalBlending;
|
|
464
|
+
FXAAShaderMaterial.uniforms.tDiffuse.value = renderTarget.texture;
|
|
465
|
+
fullScreenMesh.material = FXAAShaderMaterial;
|
|
454
466
|
fullScreenMesh.render(this.renderer);
|
|
467
|
+
// const FXAAShaderMaterial = new ShaderMaterial({
|
|
468
|
+
// uniforms: {
|
|
469
|
+
// tDiffuse: { value: null }, // 贴图纹理
|
|
470
|
+
// resolution: { value: new Vector2(1 / 1024, 1 / 1024) }
|
|
471
|
+
// },
|
|
472
|
+
// coptyShader.uniforms.map.value = renderTarget.texture;
|
|
473
|
+
// coptyShader.uniforms.opacity.value = 1.0;
|
|
474
|
+
// fullScreenMesh.material = coptyShader;
|
|
475
|
+
// coptyShader.blending = alpha ? NoBlending : NormalBlending;
|
|
476
|
+
// fullScreenMesh.render(this.renderer);
|
|
455
477
|
}
|
|
456
478
|
// 渲染纹理
|
|
457
479
|
renderTexture(texture, alpha = false) {
|
package/ThreeBase.ts
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* @Author: xiaosihan
|
|
3
3
|
* @Date: 2021-12-20 13:38:22
|
|
4
4
|
* @Last Modified by: xiaosihan
|
|
5
|
-
* @Last Modified time:
|
|
5
|
+
* @Last Modified time: 2024-01-20 05:33:28
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { round } from "lodash";
|
|
9
|
-
import { AxesHelper, BufferGeometry, Camera, DepthFormat, DepthTexture,
|
|
9
|
+
import { AxesHelper, BufferGeometry, Camera, DepthFormat, DepthTexture, EventDispatcher, GridHelper, LinearFilter, LinearSRGBColorSpace, Mesh, MeshBasicMaterial, MOUSE, NoBlending, NormalBlending, Object3D, PerspectiveCamera, RGBAFormat, Scene, Texture, TOUCH, UnsignedShortType, Vector2, Vector3, WebGLRenderer, WebGLRenderTarget } from "three";
|
|
10
10
|
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
|
11
11
|
import { generateUUID } from "three/src/math/MathUtils";
|
|
12
12
|
import glow_pass from "./pass/glow_pass";
|
|
@@ -16,6 +16,7 @@ import threeLoader from "./threeLoader";
|
|
|
16
16
|
import ThreeMouse from "./ThreeMouse";
|
|
17
17
|
import threeUtils from "./threeUtils";
|
|
18
18
|
import Transition from "./Transition";
|
|
19
|
+
import FXAAShaderMaterial from "./shaders/FXAAShaderMaterial";
|
|
19
20
|
|
|
20
21
|
// three.js 的基础对象
|
|
21
22
|
export default class ThreeBase extends EventDispatcher {
|
|
@@ -34,7 +35,6 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
34
35
|
return baseDepthTexture;
|
|
35
36
|
})();
|
|
36
37
|
|
|
37
|
-
// TODO 渲染目标的颜色空间问题 还没有处理好
|
|
38
38
|
// 基础纹理渲染对象
|
|
39
39
|
baseRenderTarget = (() => {
|
|
40
40
|
const baseRenderTarget = new WebGLRenderTarget(128, 128, {
|
|
@@ -69,14 +69,14 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
69
69
|
alpha: true,// 透明背景
|
|
70
70
|
antialias: true, // 阴影抗锯齿
|
|
71
71
|
precision: "highp", //precision:highp/mediump/lowp着色精度选择
|
|
72
|
-
logarithmicDepthBuffer: true, // 对数深度缓冲区 避免当2
|
|
72
|
+
logarithmicDepthBuffer: true, // 对数深度缓冲区 避免当2个面挨的很近时闪烁
|
|
73
73
|
preserveDrawingBuffer: true, // 是否保存绘图缓冲
|
|
74
74
|
stencil: false, // 模版
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
renderer.domElement.id = generateUUID();
|
|
78
78
|
renderer.localClippingEnabled = true;
|
|
79
|
-
renderer.outputColorSpace =
|
|
79
|
+
renderer.outputColorSpace = LinearSRGBColorSpace;
|
|
80
80
|
renderer.setPixelRatio(window.devicePixelRatio);
|
|
81
81
|
renderer.autoClear = false;
|
|
82
82
|
renderer.clear();
|
|
@@ -174,9 +174,9 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
174
174
|
controlsPosition.onChange(({ x, y, z }) => {
|
|
175
175
|
// const distance = this.controlsDistance.get("distance");
|
|
176
176
|
this.camera.position.set(x + 0.01, y, z + 0.01)
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
// .sub(this.controls.target)
|
|
178
|
+
// .setLength(distance)
|
|
179
|
+
// .add(this.controls.target);
|
|
180
180
|
|
|
181
181
|
// // 创建初始方向向量
|
|
182
182
|
// const directionVecA = new THREE.Vector3(1, 0, 0); // 需要旋转的初始方向向量
|
|
@@ -222,6 +222,9 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
222
222
|
return axesHelper;
|
|
223
223
|
})();
|
|
224
224
|
|
|
225
|
+
//TODO 设置帧频率 默认50帧
|
|
226
|
+
frame = 50;
|
|
227
|
+
|
|
225
228
|
init() {
|
|
226
229
|
// 资源加载进度有更新时, 需要渲染
|
|
227
230
|
threeLoader.addEventListener("progress", () => {
|
|
@@ -294,7 +297,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
294
297
|
return {
|
|
295
298
|
center: new Vector3(...center),
|
|
296
299
|
position: new Vector3(...position),
|
|
297
|
-
centerPosition: `
|
|
300
|
+
centerPosition: `center: new Vector3(${center.join(",")}),position: new Vector3(${position.join(",")})`
|
|
298
301
|
}
|
|
299
302
|
}
|
|
300
303
|
|
|
@@ -344,11 +347,24 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
344
347
|
this.renderer.domElement.style.opacity = "0";
|
|
345
348
|
}
|
|
346
349
|
|
|
350
|
+
// 判断是否有 发光和描边的对象 以便判断是否需要 渲染深度纹理
|
|
351
|
+
hasStrokeOrPass() {
|
|
352
|
+
let has_stroke_or_pass = false;
|
|
353
|
+
|
|
354
|
+
this.scene.traverse(obj => {
|
|
355
|
+
const { stroke_enable = false, stroke_width = 1, glow_enable = false, glow_width = 1 } = obj.userData;
|
|
356
|
+
if ((stroke_enable && stroke_width > 0) || (glow_enable && glow_width > 0)) {
|
|
357
|
+
has_stroke_or_pass = true;
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
return has_stroke_or_pass;
|
|
362
|
+
}
|
|
363
|
+
|
|
347
364
|
// 渲染场景
|
|
348
365
|
render() {
|
|
349
|
-
|
|
350
366
|
// 控制器在移动时鼠标不能操作
|
|
351
|
-
|
|
367
|
+
this.renderer.domElement.style.pointerEvents = (!this.controlsPosition.isDone() || !this.controlsCenter.isDone()) ? "none" : "all";
|
|
352
368
|
|
|
353
369
|
// canvas 没有在页面上面的话 就跳过渲染
|
|
354
370
|
if (!threeUtils.inDocument(this.renderer.domElement)) {
|
|
@@ -378,26 +394,27 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
378
394
|
// 渲染场景
|
|
379
395
|
this.dispatchEvent({ type: "beforeRender" } as never);
|
|
380
396
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
397
|
+
const has_stroke_or_pass = this.hasStrokeOrPass();
|
|
398
|
+
|
|
399
|
+
if (has_stroke_or_pass) {
|
|
400
|
+
// 把基础场景渲染到 帧缓冲区 在后期通道中会用到
|
|
401
|
+
this.renderer.setRenderTarget(this.baseRenderTarget);
|
|
402
|
+
this.renderer.clear();
|
|
403
|
+
this.renderer.render(this.scene, this.camera);
|
|
404
|
+
this.renderer.setRenderTarget(null);
|
|
405
|
+
}
|
|
385
406
|
|
|
386
407
|
// 清空主画布
|
|
387
|
-
this.renderer.setRenderTarget(null);
|
|
388
408
|
this.renderer.clear();
|
|
409
|
+
this.renderer.render(this.scene, this.camera);
|
|
389
410
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
this.scene.traverse(obj => {
|
|
398
|
-
stroke_pass(this.renderer, this.camera, obj, this.baseDepthTexture);
|
|
399
|
-
glow_pass(this.renderer, this.camera, obj, this.baseDepthTexture);
|
|
400
|
-
});
|
|
411
|
+
if (has_stroke_or_pass) {
|
|
412
|
+
// 查找需要绘制描边的对象,并且绘制描边
|
|
413
|
+
this.scene.traverse(obj => {
|
|
414
|
+
stroke_pass(this.renderer, this.camera, obj, this.baseDepthTexture);
|
|
415
|
+
glow_pass(this.renderer, this.camera, obj, this.baseDepthTexture);
|
|
416
|
+
});
|
|
417
|
+
}
|
|
401
418
|
|
|
402
419
|
this.dispatchEvent({ type: "afterRender" } as never);
|
|
403
420
|
}
|
|
@@ -546,13 +563,23 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
546
563
|
this.renderTargetgaussBlur(renderTarget, 1, 1);
|
|
547
564
|
}
|
|
548
565
|
|
|
549
|
-
//
|
|
566
|
+
// 需要做康锯齿处理 渲染 渲染目标
|
|
550
567
|
renderRendererTarget(renderTarget: WebGLRenderTarget, alpha: boolean = false) {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
fullScreenMesh.material =
|
|
554
|
-
coptyShader.blending = alpha ? NoBlending : NormalBlending;
|
|
568
|
+
|
|
569
|
+
FXAAShaderMaterial.uniforms.tDiffuse.value = renderTarget.texture;
|
|
570
|
+
fullScreenMesh.material = FXAAShaderMaterial;
|
|
555
571
|
fullScreenMesh.render(this.renderer);
|
|
572
|
+
|
|
573
|
+
// const FXAAShaderMaterial = new ShaderMaterial({
|
|
574
|
+
// uniforms: {
|
|
575
|
+
// tDiffuse: { value: null }, // 贴图纹理
|
|
576
|
+
// resolution: { value: new Vector2(1 / 1024, 1 / 1024) }
|
|
577
|
+
// },
|
|
578
|
+
// coptyShader.uniforms.map.value = renderTarget.texture;
|
|
579
|
+
// coptyShader.uniforms.opacity.value = 1.0;
|
|
580
|
+
// fullScreenMesh.material = coptyShader;
|
|
581
|
+
// coptyShader.blending = alpha ? NoBlending : NormalBlending;
|
|
582
|
+
// fullScreenMesh.render(this.renderer);
|
|
556
583
|
}
|
|
557
584
|
|
|
558
585
|
// 渲染纹理
|
package/package.json
CHANGED
package/pass/glow_pass.js
CHANGED
|
@@ -482,7 +482,7 @@ export default function glow_pass(renderer, camera, object3d, baseDepthTexture)
|
|
|
482
482
|
renderer.setRenderTarget(selectTextureTarget);
|
|
483
483
|
scene.children = [object3d];
|
|
484
484
|
renderer.clear();
|
|
485
|
-
renderer.render(
|
|
485
|
+
renderer.render(scene, camera);
|
|
486
486
|
// 设置描边着色器的分辨率
|
|
487
487
|
blurShader.uniforms.resolution.value.set(1 / size.x, 1 / size.y);
|
|
488
488
|
// 设置抗锯齿着色器的分辨率
|
package/pass/glow_pass.ts
CHANGED
|
@@ -504,7 +504,7 @@ export default function glow_pass(renderer: WebGLRenderer, camera: Camera, objec
|
|
|
504
504
|
renderer.setRenderTarget(selectTextureTarget);
|
|
505
505
|
scene.children = [object3d];
|
|
506
506
|
renderer.clear();
|
|
507
|
-
renderer.render(
|
|
507
|
+
renderer.render(scene, camera);
|
|
508
508
|
|
|
509
509
|
// 设置描边着色器的分辨率
|
|
510
510
|
blurShader.uniforms.resolution.value.set(1 / size.x, 1 / size.y);
|
package/pass/stroke_pass.js
CHANGED
|
@@ -478,7 +478,7 @@ export default function stroke_pass(renderer, camera, object3d, baseDepthTexture
|
|
|
478
478
|
renderer.setRenderTarget(selectTextureTarget);
|
|
479
479
|
scene.children = [object3d];
|
|
480
480
|
renderer.clear();
|
|
481
|
-
renderer.render(
|
|
481
|
+
renderer.render(scene, camera);
|
|
482
482
|
// 设置描边着色器的分辨率
|
|
483
483
|
blurShader.uniforms.resolution.value.set(1 / size.x, 1 / size.y);
|
|
484
484
|
// 设置抗锯齿着色器的分辨率
|
package/pass/stroke_pass.ts
CHANGED
|
@@ -497,7 +497,7 @@ export default function stroke_pass(renderer: WebGLRenderer, camera: Camera, obj
|
|
|
497
497
|
renderer.setRenderTarget(selectTextureTarget);
|
|
498
498
|
scene.children = [object3d];
|
|
499
499
|
renderer.clear();
|
|
500
|
-
renderer.render(
|
|
500
|
+
renderer.render(scene, camera);
|
|
501
501
|
|
|
502
502
|
// 设置描边着色器的分辨率
|
|
503
503
|
blurShader.uniforms.resolution.value.set(1 / size.x, 1 / size.y);
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2024-01-20 05:10:37
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2024-01-20 05:10:57
|
|
6
|
+
*/
|
|
7
|
+
import { NoBlending, ShaderChunk, ShaderMaterial, Vector2 } from "three";
|
|
8
|
+
// 抗锯齿着色器
|
|
9
|
+
const FXAAShaderMaterial = new ShaderMaterial({
|
|
10
|
+
uniforms: {
|
|
11
|
+
tDiffuse: { value: null },
|
|
12
|
+
resolution: { value: new Vector2(1 / 1024, 1 / 1024) }
|
|
13
|
+
},
|
|
14
|
+
vertexShader: `
|
|
15
|
+
${ShaderChunk.common}
|
|
16
|
+
${ShaderChunk.logdepthbuf_pars_vertex}
|
|
17
|
+
varying vec2 vUv;
|
|
18
|
+
void main() {
|
|
19
|
+
vUv = uv;
|
|
20
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
21
|
+
${ShaderChunk.logdepthbuf_vertex}
|
|
22
|
+
}
|
|
23
|
+
`,
|
|
24
|
+
fragmentShader: `
|
|
25
|
+
${ShaderChunk.logdepthbuf_pars_fragment}
|
|
26
|
+
precision highp float;
|
|
27
|
+
|
|
28
|
+
uniform sampler2D tDiffuse;
|
|
29
|
+
|
|
30
|
+
uniform vec2 resolution;
|
|
31
|
+
|
|
32
|
+
varying vec2 vUv;
|
|
33
|
+
|
|
34
|
+
#ifndef FXAA_DISCARD
|
|
35
|
+
//
|
|
36
|
+
// Only valid for PC OpenGL currently.
|
|
37
|
+
// Probably will not work when FXAA_GREEN_AS_LUMA = 1.
|
|
38
|
+
//
|
|
39
|
+
// 1 = Use discard on pixels which don't need AA.
|
|
40
|
+
// For APIs which enable concurrent TEX+ROP from same surface.
|
|
41
|
+
// 0 = Return unchanged color on pixels which don't need AA.
|
|
42
|
+
//
|
|
43
|
+
#define FXAA_DISCARD 0
|
|
44
|
+
#endif
|
|
45
|
+
|
|
46
|
+
/*--------------------------------------------------------------------------*/
|
|
47
|
+
#define FxaaTexTop(t, p) texture2D(t, p, -100.0)
|
|
48
|
+
#define FxaaTexOff(t, p, o, r) texture2D(t, p + (o * r), -100.0)
|
|
49
|
+
/*--------------------------------------------------------------------------*/
|
|
50
|
+
|
|
51
|
+
#define NUM_SAMPLES 5
|
|
52
|
+
|
|
53
|
+
// assumes colors have premultipliedAlpha, so that the calculated color contrast is scaled by alpha
|
|
54
|
+
float contrast( vec4 a, vec4 b ) {
|
|
55
|
+
vec4 diff = abs( a - b );
|
|
56
|
+
return max( max( max( diff.r, diff.g ), diff.b ), diff.a );
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/*============================================================================
|
|
60
|
+
|
|
61
|
+
FXAA3 QUALITY - PC
|
|
62
|
+
|
|
63
|
+
============================================================================*/
|
|
64
|
+
|
|
65
|
+
/*--------------------------------------------------------------------------*/
|
|
66
|
+
vec4 FxaaPixelShader(
|
|
67
|
+
vec2 posM,
|
|
68
|
+
sampler2D tex,
|
|
69
|
+
vec2 fxaaQualityRcpFrame,
|
|
70
|
+
float fxaaQualityEdgeThreshold,
|
|
71
|
+
float fxaaQualityinvEdgeThreshold
|
|
72
|
+
) {
|
|
73
|
+
vec4 rgbaM = FxaaTexTop(tex, posM);
|
|
74
|
+
vec4 rgbaS = FxaaTexOff(tex, posM, vec2( 0.0, 1.0), fxaaQualityRcpFrame.xy);
|
|
75
|
+
vec4 rgbaE = FxaaTexOff(tex, posM, vec2( 1.0, 0.0), fxaaQualityRcpFrame.xy);
|
|
76
|
+
vec4 rgbaN = FxaaTexOff(tex, posM, vec2( 0.0,-1.0), fxaaQualityRcpFrame.xy);
|
|
77
|
+
vec4 rgbaW = FxaaTexOff(tex, posM, vec2(-1.0, 0.0), fxaaQualityRcpFrame.xy);
|
|
78
|
+
// . S .
|
|
79
|
+
// W M E
|
|
80
|
+
// . N .
|
|
81
|
+
|
|
82
|
+
bool earlyExit = max( max( max(
|
|
83
|
+
contrast( rgbaM, rgbaN ),
|
|
84
|
+
contrast( rgbaM, rgbaS ) ),
|
|
85
|
+
contrast( rgbaM, rgbaE ) ),
|
|
86
|
+
contrast( rgbaM, rgbaW ) )
|
|
87
|
+
< fxaaQualityEdgeThreshold;
|
|
88
|
+
// . 0 .
|
|
89
|
+
// 0 0 0
|
|
90
|
+
// . 0 .
|
|
91
|
+
|
|
92
|
+
#if (FXAA_DISCARD == 1)
|
|
93
|
+
if(earlyExit) FxaaDiscard;
|
|
94
|
+
#else
|
|
95
|
+
if(earlyExit) return rgbaM;
|
|
96
|
+
#endif
|
|
97
|
+
|
|
98
|
+
float contrastN = contrast( rgbaM, rgbaN );
|
|
99
|
+
float contrastS = contrast( rgbaM, rgbaS );
|
|
100
|
+
float contrastE = contrast( rgbaM, rgbaE );
|
|
101
|
+
float contrastW = contrast( rgbaM, rgbaW );
|
|
102
|
+
|
|
103
|
+
float relativeVContrast = ( contrastN + contrastS ) - ( contrastE + contrastW );
|
|
104
|
+
relativeVContrast *= fxaaQualityinvEdgeThreshold;
|
|
105
|
+
|
|
106
|
+
bool horzSpan = relativeVContrast > 0.;
|
|
107
|
+
// . 1 .
|
|
108
|
+
// 0 0 0
|
|
109
|
+
// . 1 .
|
|
110
|
+
|
|
111
|
+
// 45 deg edge detection and corners of objects, aka V/H contrast is too similar
|
|
112
|
+
if( abs( relativeVContrast ) < .3 ) {
|
|
113
|
+
// locate the edge
|
|
114
|
+
vec2 dirToEdge;
|
|
115
|
+
dirToEdge.x = contrastE > contrastW ? 1. : -1.;
|
|
116
|
+
dirToEdge.y = contrastS > contrastN ? 1. : -1.;
|
|
117
|
+
// . 2 . . 1 .
|
|
118
|
+
// 1 0 2 ~= 0 0 1
|
|
119
|
+
// . 1 . . 0 .
|
|
120
|
+
|
|
121
|
+
// tap 2 pixels and see which ones are "outside" the edge, to
|
|
122
|
+
// determine if the edge is vertical or horizontal
|
|
123
|
+
|
|
124
|
+
vec4 rgbaAlongH = FxaaTexOff(tex, posM, vec2( dirToEdge.x, -dirToEdge.y ), fxaaQualityRcpFrame.xy);
|
|
125
|
+
float matchAlongH = contrast( rgbaM, rgbaAlongH );
|
|
126
|
+
// . 1 .
|
|
127
|
+
// 0 0 1
|
|
128
|
+
// . 0 H
|
|
129
|
+
|
|
130
|
+
vec4 rgbaAlongV = FxaaTexOff(tex, posM, vec2( -dirToEdge.x, dirToEdge.y ), fxaaQualityRcpFrame.xy);
|
|
131
|
+
float matchAlongV = contrast( rgbaM, rgbaAlongV );
|
|
132
|
+
// V 1 .
|
|
133
|
+
// 0 0 1
|
|
134
|
+
// . 0 .
|
|
135
|
+
|
|
136
|
+
relativeVContrast = matchAlongV - matchAlongH;
|
|
137
|
+
relativeVContrast *= fxaaQualityinvEdgeThreshold;
|
|
138
|
+
|
|
139
|
+
if( abs( relativeVContrast ) < .3 ) { // 45 deg edge
|
|
140
|
+
// 1 1 .
|
|
141
|
+
// 0 0 1
|
|
142
|
+
// . 0 1
|
|
143
|
+
|
|
144
|
+
// do a simple blur
|
|
145
|
+
return mix(
|
|
146
|
+
rgbaM,
|
|
147
|
+
(rgbaN + rgbaS + rgbaE + rgbaW) * .25,
|
|
148
|
+
.4
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
horzSpan = relativeVContrast > 0.;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if(!horzSpan) rgbaN = rgbaW;
|
|
156
|
+
if(!horzSpan) rgbaS = rgbaE;
|
|
157
|
+
// . 0 . 1
|
|
158
|
+
// 1 0 1 -> 0
|
|
159
|
+
// . 0 . 1
|
|
160
|
+
|
|
161
|
+
bool pairN = contrast( rgbaM, rgbaN ) > contrast( rgbaM, rgbaS );
|
|
162
|
+
if(!pairN) rgbaN = rgbaS;
|
|
163
|
+
|
|
164
|
+
vec2 offNP;
|
|
165
|
+
offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
|
|
166
|
+
offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
|
|
167
|
+
|
|
168
|
+
bool doneN = false;
|
|
169
|
+
bool doneP = false;
|
|
170
|
+
|
|
171
|
+
float nDist = 0.;
|
|
172
|
+
float pDist = 0.;
|
|
173
|
+
|
|
174
|
+
vec2 posN = posM;
|
|
175
|
+
vec2 posP = posM;
|
|
176
|
+
|
|
177
|
+
int iterationsUsed = 0;
|
|
178
|
+
int iterationsUsedN = 0;
|
|
179
|
+
int iterationsUsedP = 0;
|
|
180
|
+
for( int i = 0; i < NUM_SAMPLES; i++ ) {
|
|
181
|
+
iterationsUsed = i;
|
|
182
|
+
|
|
183
|
+
float increment = float(i + 1);
|
|
184
|
+
|
|
185
|
+
if(!doneN) {
|
|
186
|
+
nDist += increment;
|
|
187
|
+
posN = posM + offNP * nDist;
|
|
188
|
+
vec4 rgbaEndN = FxaaTexTop(tex, posN.xy);
|
|
189
|
+
doneN = contrast( rgbaEndN, rgbaM ) > contrast( rgbaEndN, rgbaN );
|
|
190
|
+
iterationsUsedN = i;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if(!doneP) {
|
|
194
|
+
pDist += increment;
|
|
195
|
+
posP = posM - offNP * pDist;
|
|
196
|
+
vec4 rgbaEndP = FxaaTexTop(tex, posP.xy);
|
|
197
|
+
doneP = contrast( rgbaEndP, rgbaM ) > contrast( rgbaEndP, rgbaN );
|
|
198
|
+
iterationsUsedP = i;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if(doneN || doneP) break;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
if ( !doneP && !doneN ) return rgbaM; // failed to find end of edge
|
|
206
|
+
|
|
207
|
+
float dist = min(
|
|
208
|
+
doneN ? float( iterationsUsedN ) / float( NUM_SAMPLES - 1 ) : 1.,
|
|
209
|
+
doneP ? float( iterationsUsedP ) / float( NUM_SAMPLES - 1 ) : 1.
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
// hacky way of reduces blurriness of mostly diagonal edges
|
|
213
|
+
// but reduces AA quality
|
|
214
|
+
dist = pow(dist, .5);
|
|
215
|
+
|
|
216
|
+
dist = 1. - dist;
|
|
217
|
+
|
|
218
|
+
return mix(
|
|
219
|
+
rgbaM,
|
|
220
|
+
rgbaN,
|
|
221
|
+
dist * .5
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
void main() {
|
|
226
|
+
const float edgeDetectionQuality = .2;
|
|
227
|
+
const float invEdgeDetectionQuality = 1. / edgeDetectionQuality;
|
|
228
|
+
|
|
229
|
+
gl_FragColor = FxaaPixelShader(
|
|
230
|
+
vUv,
|
|
231
|
+
tDiffuse,
|
|
232
|
+
resolution,
|
|
233
|
+
edgeDetectionQuality, // [0,1] contrast needed, otherwise early discard
|
|
234
|
+
invEdgeDetectionQuality
|
|
235
|
+
);
|
|
236
|
+
${ShaderChunk.logdepthbuf_fragment}
|
|
237
|
+
}
|
|
238
|
+
`,
|
|
239
|
+
blending: NoBlending,
|
|
240
|
+
depthTest: false,
|
|
241
|
+
depthWrite: false,
|
|
242
|
+
transparent: true
|
|
243
|
+
});
|
|
244
|
+
export default FXAAShaderMaterial;
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2024-01-20 05:10:37
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2024-01-20 05:10:57
|
|
6
|
+
*/
|
|
7
|
+
import { NoBlending, ShaderChunk, ShaderMaterial, Vector2 } from "three";
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
// 抗锯齿着色器
|
|
12
|
+
const FXAAShaderMaterial = new ShaderMaterial({
|
|
13
|
+
uniforms: {
|
|
14
|
+
tDiffuse: { value: null }, // 贴图纹理
|
|
15
|
+
resolution: { value: new Vector2(1 / 1024, 1 / 1024) }
|
|
16
|
+
},
|
|
17
|
+
vertexShader: `
|
|
18
|
+
${ShaderChunk.common}
|
|
19
|
+
${ShaderChunk.logdepthbuf_pars_vertex}
|
|
20
|
+
varying vec2 vUv;
|
|
21
|
+
void main() {
|
|
22
|
+
vUv = uv;
|
|
23
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
24
|
+
${ShaderChunk.logdepthbuf_vertex}
|
|
25
|
+
}
|
|
26
|
+
`,
|
|
27
|
+
fragmentShader: `
|
|
28
|
+
${ShaderChunk.logdepthbuf_pars_fragment}
|
|
29
|
+
precision highp float;
|
|
30
|
+
|
|
31
|
+
uniform sampler2D tDiffuse;
|
|
32
|
+
|
|
33
|
+
uniform vec2 resolution;
|
|
34
|
+
|
|
35
|
+
varying vec2 vUv;
|
|
36
|
+
|
|
37
|
+
#ifndef FXAA_DISCARD
|
|
38
|
+
//
|
|
39
|
+
// Only valid for PC OpenGL currently.
|
|
40
|
+
// Probably will not work when FXAA_GREEN_AS_LUMA = 1.
|
|
41
|
+
//
|
|
42
|
+
// 1 = Use discard on pixels which don't need AA.
|
|
43
|
+
// For APIs which enable concurrent TEX+ROP from same surface.
|
|
44
|
+
// 0 = Return unchanged color on pixels which don't need AA.
|
|
45
|
+
//
|
|
46
|
+
#define FXAA_DISCARD 0
|
|
47
|
+
#endif
|
|
48
|
+
|
|
49
|
+
/*--------------------------------------------------------------------------*/
|
|
50
|
+
#define FxaaTexTop(t, p) texture2D(t, p, -100.0)
|
|
51
|
+
#define FxaaTexOff(t, p, o, r) texture2D(t, p + (o * r), -100.0)
|
|
52
|
+
/*--------------------------------------------------------------------------*/
|
|
53
|
+
|
|
54
|
+
#define NUM_SAMPLES 5
|
|
55
|
+
|
|
56
|
+
// assumes colors have premultipliedAlpha, so that the calculated color contrast is scaled by alpha
|
|
57
|
+
float contrast( vec4 a, vec4 b ) {
|
|
58
|
+
vec4 diff = abs( a - b );
|
|
59
|
+
return max( max( max( diff.r, diff.g ), diff.b ), diff.a );
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/*============================================================================
|
|
63
|
+
|
|
64
|
+
FXAA3 QUALITY - PC
|
|
65
|
+
|
|
66
|
+
============================================================================*/
|
|
67
|
+
|
|
68
|
+
/*--------------------------------------------------------------------------*/
|
|
69
|
+
vec4 FxaaPixelShader(
|
|
70
|
+
vec2 posM,
|
|
71
|
+
sampler2D tex,
|
|
72
|
+
vec2 fxaaQualityRcpFrame,
|
|
73
|
+
float fxaaQualityEdgeThreshold,
|
|
74
|
+
float fxaaQualityinvEdgeThreshold
|
|
75
|
+
) {
|
|
76
|
+
vec4 rgbaM = FxaaTexTop(tex, posM);
|
|
77
|
+
vec4 rgbaS = FxaaTexOff(tex, posM, vec2( 0.0, 1.0), fxaaQualityRcpFrame.xy);
|
|
78
|
+
vec4 rgbaE = FxaaTexOff(tex, posM, vec2( 1.0, 0.0), fxaaQualityRcpFrame.xy);
|
|
79
|
+
vec4 rgbaN = FxaaTexOff(tex, posM, vec2( 0.0,-1.0), fxaaQualityRcpFrame.xy);
|
|
80
|
+
vec4 rgbaW = FxaaTexOff(tex, posM, vec2(-1.0, 0.0), fxaaQualityRcpFrame.xy);
|
|
81
|
+
// . S .
|
|
82
|
+
// W M E
|
|
83
|
+
// . N .
|
|
84
|
+
|
|
85
|
+
bool earlyExit = max( max( max(
|
|
86
|
+
contrast( rgbaM, rgbaN ),
|
|
87
|
+
contrast( rgbaM, rgbaS ) ),
|
|
88
|
+
contrast( rgbaM, rgbaE ) ),
|
|
89
|
+
contrast( rgbaM, rgbaW ) )
|
|
90
|
+
< fxaaQualityEdgeThreshold;
|
|
91
|
+
// . 0 .
|
|
92
|
+
// 0 0 0
|
|
93
|
+
// . 0 .
|
|
94
|
+
|
|
95
|
+
#if (FXAA_DISCARD == 1)
|
|
96
|
+
if(earlyExit) FxaaDiscard;
|
|
97
|
+
#else
|
|
98
|
+
if(earlyExit) return rgbaM;
|
|
99
|
+
#endif
|
|
100
|
+
|
|
101
|
+
float contrastN = contrast( rgbaM, rgbaN );
|
|
102
|
+
float contrastS = contrast( rgbaM, rgbaS );
|
|
103
|
+
float contrastE = contrast( rgbaM, rgbaE );
|
|
104
|
+
float contrastW = contrast( rgbaM, rgbaW );
|
|
105
|
+
|
|
106
|
+
float relativeVContrast = ( contrastN + contrastS ) - ( contrastE + contrastW );
|
|
107
|
+
relativeVContrast *= fxaaQualityinvEdgeThreshold;
|
|
108
|
+
|
|
109
|
+
bool horzSpan = relativeVContrast > 0.;
|
|
110
|
+
// . 1 .
|
|
111
|
+
// 0 0 0
|
|
112
|
+
// . 1 .
|
|
113
|
+
|
|
114
|
+
// 45 deg edge detection and corners of objects, aka V/H contrast is too similar
|
|
115
|
+
if( abs( relativeVContrast ) < .3 ) {
|
|
116
|
+
// locate the edge
|
|
117
|
+
vec2 dirToEdge;
|
|
118
|
+
dirToEdge.x = contrastE > contrastW ? 1. : -1.;
|
|
119
|
+
dirToEdge.y = contrastS > contrastN ? 1. : -1.;
|
|
120
|
+
// . 2 . . 1 .
|
|
121
|
+
// 1 0 2 ~= 0 0 1
|
|
122
|
+
// . 1 . . 0 .
|
|
123
|
+
|
|
124
|
+
// tap 2 pixels and see which ones are "outside" the edge, to
|
|
125
|
+
// determine if the edge is vertical or horizontal
|
|
126
|
+
|
|
127
|
+
vec4 rgbaAlongH = FxaaTexOff(tex, posM, vec2( dirToEdge.x, -dirToEdge.y ), fxaaQualityRcpFrame.xy);
|
|
128
|
+
float matchAlongH = contrast( rgbaM, rgbaAlongH );
|
|
129
|
+
// . 1 .
|
|
130
|
+
// 0 0 1
|
|
131
|
+
// . 0 H
|
|
132
|
+
|
|
133
|
+
vec4 rgbaAlongV = FxaaTexOff(tex, posM, vec2( -dirToEdge.x, dirToEdge.y ), fxaaQualityRcpFrame.xy);
|
|
134
|
+
float matchAlongV = contrast( rgbaM, rgbaAlongV );
|
|
135
|
+
// V 1 .
|
|
136
|
+
// 0 0 1
|
|
137
|
+
// . 0 .
|
|
138
|
+
|
|
139
|
+
relativeVContrast = matchAlongV - matchAlongH;
|
|
140
|
+
relativeVContrast *= fxaaQualityinvEdgeThreshold;
|
|
141
|
+
|
|
142
|
+
if( abs( relativeVContrast ) < .3 ) { // 45 deg edge
|
|
143
|
+
// 1 1 .
|
|
144
|
+
// 0 0 1
|
|
145
|
+
// . 0 1
|
|
146
|
+
|
|
147
|
+
// do a simple blur
|
|
148
|
+
return mix(
|
|
149
|
+
rgbaM,
|
|
150
|
+
(rgbaN + rgbaS + rgbaE + rgbaW) * .25,
|
|
151
|
+
.4
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
horzSpan = relativeVContrast > 0.;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if(!horzSpan) rgbaN = rgbaW;
|
|
159
|
+
if(!horzSpan) rgbaS = rgbaE;
|
|
160
|
+
// . 0 . 1
|
|
161
|
+
// 1 0 1 -> 0
|
|
162
|
+
// . 0 . 1
|
|
163
|
+
|
|
164
|
+
bool pairN = contrast( rgbaM, rgbaN ) > contrast( rgbaM, rgbaS );
|
|
165
|
+
if(!pairN) rgbaN = rgbaS;
|
|
166
|
+
|
|
167
|
+
vec2 offNP;
|
|
168
|
+
offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
|
|
169
|
+
offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
|
|
170
|
+
|
|
171
|
+
bool doneN = false;
|
|
172
|
+
bool doneP = false;
|
|
173
|
+
|
|
174
|
+
float nDist = 0.;
|
|
175
|
+
float pDist = 0.;
|
|
176
|
+
|
|
177
|
+
vec2 posN = posM;
|
|
178
|
+
vec2 posP = posM;
|
|
179
|
+
|
|
180
|
+
int iterationsUsed = 0;
|
|
181
|
+
int iterationsUsedN = 0;
|
|
182
|
+
int iterationsUsedP = 0;
|
|
183
|
+
for( int i = 0; i < NUM_SAMPLES; i++ ) {
|
|
184
|
+
iterationsUsed = i;
|
|
185
|
+
|
|
186
|
+
float increment = float(i + 1);
|
|
187
|
+
|
|
188
|
+
if(!doneN) {
|
|
189
|
+
nDist += increment;
|
|
190
|
+
posN = posM + offNP * nDist;
|
|
191
|
+
vec4 rgbaEndN = FxaaTexTop(tex, posN.xy);
|
|
192
|
+
doneN = contrast( rgbaEndN, rgbaM ) > contrast( rgbaEndN, rgbaN );
|
|
193
|
+
iterationsUsedN = i;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if(!doneP) {
|
|
197
|
+
pDist += increment;
|
|
198
|
+
posP = posM - offNP * pDist;
|
|
199
|
+
vec4 rgbaEndP = FxaaTexTop(tex, posP.xy);
|
|
200
|
+
doneP = contrast( rgbaEndP, rgbaM ) > contrast( rgbaEndP, rgbaN );
|
|
201
|
+
iterationsUsedP = i;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if(doneN || doneP) break;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
if ( !doneP && !doneN ) return rgbaM; // failed to find end of edge
|
|
209
|
+
|
|
210
|
+
float dist = min(
|
|
211
|
+
doneN ? float( iterationsUsedN ) / float( NUM_SAMPLES - 1 ) : 1.,
|
|
212
|
+
doneP ? float( iterationsUsedP ) / float( NUM_SAMPLES - 1 ) : 1.
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
// hacky way of reduces blurriness of mostly diagonal edges
|
|
216
|
+
// but reduces AA quality
|
|
217
|
+
dist = pow(dist, .5);
|
|
218
|
+
|
|
219
|
+
dist = 1. - dist;
|
|
220
|
+
|
|
221
|
+
return mix(
|
|
222
|
+
rgbaM,
|
|
223
|
+
rgbaN,
|
|
224
|
+
dist * .5
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
void main() {
|
|
229
|
+
const float edgeDetectionQuality = .2;
|
|
230
|
+
const float invEdgeDetectionQuality = 1. / edgeDetectionQuality;
|
|
231
|
+
|
|
232
|
+
gl_FragColor = FxaaPixelShader(
|
|
233
|
+
vUv,
|
|
234
|
+
tDiffuse,
|
|
235
|
+
resolution,
|
|
236
|
+
edgeDetectionQuality, // [0,1] contrast needed, otherwise early discard
|
|
237
|
+
invEdgeDetectionQuality
|
|
238
|
+
);
|
|
239
|
+
${ShaderChunk.logdepthbuf_fragment}
|
|
240
|
+
}
|
|
241
|
+
`,
|
|
242
|
+
blending: NoBlending, // 渲染时不与背景融合计算 直接替换
|
|
243
|
+
depthTest: false,
|
|
244
|
+
depthWrite: false,
|
|
245
|
+
transparent: true
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
export default FXAAShaderMaterial;
|