three-base 2.0.6 → 2.0.8

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.
@@ -4,7 +4,7 @@
4
4
  * @Last Modified by: xiaosihan
5
5
  * @Last Modified time: 2023-05-09 02:33:28
6
6
  */
7
- import { LinearFilter, RGBAFormat, Vector2, WebGLRenderTarget, NoBlending, Scene, RawShaderMaterial, Color, NormalBlending } from "three";
7
+ import { LinearFilter, RGBAFormat, Vector2, WebGLRenderTarget, ShaderMaterial, NoBlending, Scene, RawShaderMaterial, Color, NormalBlending, ShaderChunk } from "three";
8
8
  import FullScreenQuad from "./FullScreenQuad";
9
9
  // 选中对象的纹理
10
10
  const selectTextureTarget = new WebGLRenderTarget(512, 512, { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat });
@@ -15,6 +15,242 @@ const blur2TextureTarget = new WebGLRenderTarget(512, 512, { minFilter: LinearFi
15
15
  const size = new Vector2();
16
16
  // 创建一个渲染工具 用于处理纹理
17
17
  const fsQuad = new FullScreenQuad(); // 渲染辅助器
18
+ // 抗锯齿着色器
19
+ const FXAAShaderMaterial = new ShaderMaterial({
20
+ uniforms: {
21
+ tDiffuse: { value: null },
22
+ resolution: { value: new Vector2(1 / 1024, 1 / 1024) }
23
+ },
24
+ vertexShader: `
25
+ ${ShaderChunk.common}
26
+ ${ShaderChunk.logdepthbuf_pars_vertex}
27
+ varying vec2 vUv;
28
+ void main() {
29
+ vUv = uv;
30
+ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
31
+ ${ShaderChunk.logdepthbuf_vertex}
32
+ }
33
+ `,
34
+ fragmentShader: `
35
+ ${ShaderChunk.logdepthbuf_pars_fragment}
36
+ precision highp float;
37
+
38
+ uniform sampler2D tDiffuse;
39
+
40
+ uniform vec2 resolution;
41
+
42
+ varying vec2 vUv;
43
+
44
+ #ifndef FXAA_DISCARD
45
+ //
46
+ // Only valid for PC OpenGL currently.
47
+ // Probably will not work when FXAA_GREEN_AS_LUMA = 1.
48
+ //
49
+ // 1 = Use discard on pixels which don't need AA.
50
+ // For APIs which enable concurrent TEX+ROP from same surface.
51
+ // 0 = Return unchanged color on pixels which don't need AA.
52
+ //
53
+ #define FXAA_DISCARD 0
54
+ #endif
55
+
56
+ /*--------------------------------------------------------------------------*/
57
+ #define FxaaTexTop(t, p) texture2D(t, p, -100.0)
58
+ #define FxaaTexOff(t, p, o, r) texture2D(t, p + (o * r), -100.0)
59
+ /*--------------------------------------------------------------------------*/
60
+
61
+ #define NUM_SAMPLES 5
62
+
63
+ // assumes colors have premultipliedAlpha, so that the calculated color contrast is scaled by alpha
64
+ float contrast( vec4 a, vec4 b ) {
65
+ vec4 diff = abs( a - b );
66
+ return max( max( max( diff.r, diff.g ), diff.b ), diff.a );
67
+ }
68
+
69
+ /*============================================================================
70
+
71
+ FXAA3 QUALITY - PC
72
+
73
+ ============================================================================*/
74
+
75
+ /*--------------------------------------------------------------------------*/
76
+ vec4 FxaaPixelShader(
77
+ vec2 posM,
78
+ sampler2D tex,
79
+ vec2 fxaaQualityRcpFrame,
80
+ float fxaaQualityEdgeThreshold,
81
+ float fxaaQualityinvEdgeThreshold
82
+ ) {
83
+ vec4 rgbaM = FxaaTexTop(tex, posM);
84
+ vec4 rgbaS = FxaaTexOff(tex, posM, vec2( 0.0, 1.0), fxaaQualityRcpFrame.xy);
85
+ vec4 rgbaE = FxaaTexOff(tex, posM, vec2( 1.0, 0.0), fxaaQualityRcpFrame.xy);
86
+ vec4 rgbaN = FxaaTexOff(tex, posM, vec2( 0.0,-1.0), fxaaQualityRcpFrame.xy);
87
+ vec4 rgbaW = FxaaTexOff(tex, posM, vec2(-1.0, 0.0), fxaaQualityRcpFrame.xy);
88
+ // . S .
89
+ // W M E
90
+ // . N .
91
+
92
+ bool earlyExit = max( max( max(
93
+ contrast( rgbaM, rgbaN ),
94
+ contrast( rgbaM, rgbaS ) ),
95
+ contrast( rgbaM, rgbaE ) ),
96
+ contrast( rgbaM, rgbaW ) )
97
+ < fxaaQualityEdgeThreshold;
98
+ // . 0 .
99
+ // 0 0 0
100
+ // . 0 .
101
+
102
+ #if (FXAA_DISCARD == 1)
103
+ if(earlyExit) FxaaDiscard;
104
+ #else
105
+ if(earlyExit) return rgbaM;
106
+ #endif
107
+
108
+ float contrastN = contrast( rgbaM, rgbaN );
109
+ float contrastS = contrast( rgbaM, rgbaS );
110
+ float contrastE = contrast( rgbaM, rgbaE );
111
+ float contrastW = contrast( rgbaM, rgbaW );
112
+
113
+ float relativeVContrast = ( contrastN + contrastS ) - ( contrastE + contrastW );
114
+ relativeVContrast *= fxaaQualityinvEdgeThreshold;
115
+
116
+ bool horzSpan = relativeVContrast > 0.;
117
+ // . 1 .
118
+ // 0 0 0
119
+ // . 1 .
120
+
121
+ // 45 deg edge detection and corners of objects, aka V/H contrast is too similar
122
+ if( abs( relativeVContrast ) < .3 ) {
123
+ // locate the edge
124
+ vec2 dirToEdge;
125
+ dirToEdge.x = contrastE > contrastW ? 1. : -1.;
126
+ dirToEdge.y = contrastS > contrastN ? 1. : -1.;
127
+ // . 2 . . 1 .
128
+ // 1 0 2 ~= 0 0 1
129
+ // . 1 . . 0 .
130
+
131
+ // tap 2 pixels and see which ones are "outside" the edge, to
132
+ // determine if the edge is vertical or horizontal
133
+
134
+ vec4 rgbaAlongH = FxaaTexOff(tex, posM, vec2( dirToEdge.x, -dirToEdge.y ), fxaaQualityRcpFrame.xy);
135
+ float matchAlongH = contrast( rgbaM, rgbaAlongH );
136
+ // . 1 .
137
+ // 0 0 1
138
+ // . 0 H
139
+
140
+ vec4 rgbaAlongV = FxaaTexOff(tex, posM, vec2( -dirToEdge.x, dirToEdge.y ), fxaaQualityRcpFrame.xy);
141
+ float matchAlongV = contrast( rgbaM, rgbaAlongV );
142
+ // V 1 .
143
+ // 0 0 1
144
+ // . 0 .
145
+
146
+ relativeVContrast = matchAlongV - matchAlongH;
147
+ relativeVContrast *= fxaaQualityinvEdgeThreshold;
148
+
149
+ if( abs( relativeVContrast ) < .3 ) { // 45 deg edge
150
+ // 1 1 .
151
+ // 0 0 1
152
+ // . 0 1
153
+
154
+ // do a simple blur
155
+ return mix(
156
+ rgbaM,
157
+ (rgbaN + rgbaS + rgbaE + rgbaW) * .25,
158
+ .4
159
+ );
160
+ }
161
+
162
+ horzSpan = relativeVContrast > 0.;
163
+ }
164
+
165
+ if(!horzSpan) rgbaN = rgbaW;
166
+ if(!horzSpan) rgbaS = rgbaE;
167
+ // . 0 . 1
168
+ // 1 0 1 -> 0
169
+ // . 0 . 1
170
+
171
+ bool pairN = contrast( rgbaM, rgbaN ) > contrast( rgbaM, rgbaS );
172
+ if(!pairN) rgbaN = rgbaS;
173
+
174
+ vec2 offNP;
175
+ offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
176
+ offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
177
+
178
+ bool doneN = false;
179
+ bool doneP = false;
180
+
181
+ float nDist = 0.;
182
+ float pDist = 0.;
183
+
184
+ vec2 posN = posM;
185
+ vec2 posP = posM;
186
+
187
+ int iterationsUsed = 0;
188
+ int iterationsUsedN = 0;
189
+ int iterationsUsedP = 0;
190
+ for( int i = 0; i < NUM_SAMPLES; i++ ) {
191
+ iterationsUsed = i;
192
+
193
+ float increment = float(i + 1);
194
+
195
+ if(!doneN) {
196
+ nDist += increment;
197
+ posN = posM + offNP * nDist;
198
+ vec4 rgbaEndN = FxaaTexTop(tex, posN.xy);
199
+ doneN = contrast( rgbaEndN, rgbaM ) > contrast( rgbaEndN, rgbaN );
200
+ iterationsUsedN = i;
201
+ }
202
+
203
+ if(!doneP) {
204
+ pDist += increment;
205
+ posP = posM - offNP * pDist;
206
+ vec4 rgbaEndP = FxaaTexTop(tex, posP.xy);
207
+ doneP = contrast( rgbaEndP, rgbaM ) > contrast( rgbaEndP, rgbaN );
208
+ iterationsUsedP = i;
209
+ }
210
+
211
+ if(doneN || doneP) break;
212
+ }
213
+
214
+
215
+ if ( !doneP && !doneN ) return rgbaM; // failed to find end of edge
216
+
217
+ float dist = min(
218
+ doneN ? float( iterationsUsedN ) / float( NUM_SAMPLES - 1 ) : 1.,
219
+ doneP ? float( iterationsUsedP ) / float( NUM_SAMPLES - 1 ) : 1.
220
+ );
221
+
222
+ // hacky way of reduces blurriness of mostly diagonal edges
223
+ // but reduces AA quality
224
+ dist = pow(dist, .5);
225
+
226
+ dist = 1. - dist;
227
+
228
+ return mix(
229
+ rgbaM,
230
+ rgbaN,
231
+ dist * .5
232
+ );
233
+ }
234
+
235
+ void main() {
236
+ const float edgeDetectionQuality = .2;
237
+ const float invEdgeDetectionQuality = 1. / edgeDetectionQuality;
238
+
239
+ gl_FragColor = FxaaPixelShader(
240
+ vUv,
241
+ tDiffuse,
242
+ resolution,
243
+ edgeDetectionQuality, // [0,1] contrast needed, otherwise early discard
244
+ invEdgeDetectionQuality
245
+ );
246
+ ${ShaderChunk.logdepthbuf_fragment}
247
+ }
248
+ `,
249
+ blending: NoBlending,
250
+ depthTest: false,
251
+ depthWrite: false,
252
+ transparent: true
253
+ });
18
254
  // 描边着色器
19
255
  const blurShader = new RawShaderMaterial({
20
256
  uniforms: {
@@ -140,7 +376,7 @@ const scene = new Scene();
140
376
  // 对象描边
141
377
  export default function stroke_pass(renderer, camera, object3d) {
142
378
  const { stroke_enable = false, stroke_color = "#04fa12", stroke_width = 1 } = object3d.userData;
143
- if (!stroke_enable) {
379
+ if (!stroke_enable || stroke_width === 0) {
144
380
  return;
145
381
  }
146
382
  // 保存原帧缓冲区
@@ -156,6 +392,8 @@ export default function stroke_pass(renderer, camera, object3d) {
156
392
  renderer.render(object3d, camera);
157
393
  // 设置描边着色器的分辨率
158
394
  blurShader.uniforms.resolution.value.set(1 / size.x, 1 / size.y);
395
+ // 设置抗锯齿着色器的分辨率
396
+ FXAAShaderMaterial.uniforms.resolution.value.set(1 / size.x, 1 / size.y);
159
397
  //描边颜色
160
398
  blurShader.uniforms.color.value.set(stroke_color);
161
399
  blurShader.uniforms.width.value = stroke_width / 4;
@@ -175,10 +413,14 @@ export default function stroke_pass(renderer, camera, object3d) {
175
413
  renderer.setRenderTarget(blur2TextureTarget);
176
414
  blurShader.uniforms.tDiffuse.value = blur1TextureTarget.texture;
177
415
  fsQuad.render(renderer, blurShader);
416
+ //最后抗锯齿
417
+ renderer.setRenderTarget(blur1TextureTarget);
418
+ FXAAShaderMaterial.uniforms.tDiffuse.value = blur2TextureTarget.texture;
419
+ fsQuad.render(renderer, FXAAShaderMaterial);
178
420
  // 还原帧缓冲区 减去原始纹理保留描边
179
421
  renderer.setRenderTarget(originRenderTarget);
180
422
  filterSelectShader.uniforms.selectTexture.value = selectTextureTarget.texture;
181
- filterSelectShader.uniforms.blurTexture.value = blur2TextureTarget.texture;
423
+ filterSelectShader.uniforms.blurTexture.value = blur1TextureTarget.texture;
182
424
  filterSelectShader.blending = NormalBlending; // 与有的纹理融合计算 保留前面通道传递下来的纹理
183
425
  fsQuad.render(renderer, filterSelectShader);
184
426
  // 调试代码
@@ -5,7 +5,7 @@
5
5
  * @Last Modified time: 2023-05-09 02:33:28
6
6
  */
7
7
 
8
- import { Camera, LinearFilter, Object3D, RGBAFormat, Vector2, WebGLRenderTarget, WebGLRenderer, ShaderMaterial, NoBlending, Scene, RawShaderMaterial, Color, NormalBlending } from "three";
8
+ import { Camera, LinearFilter, Object3D, RGBAFormat, Vector2, WebGLRenderTarget, WebGLRenderer, ShaderMaterial, NoBlending, Scene, RawShaderMaterial, Color, NormalBlending, ShaderChunk } from "three";
9
9
  import FullScreenQuad from "./FullScreenQuad";
10
10
 
11
11
  // 选中对象的纹理
@@ -22,6 +22,243 @@ const size = new Vector2();
22
22
  // 创建一个渲染工具 用于处理纹理
23
23
  const fsQuad = new FullScreenQuad(); // 渲染辅助器
24
24
 
25
+ // 抗锯齿着色器
26
+ const FXAAShaderMaterial = new ShaderMaterial({
27
+ uniforms: {
28
+ tDiffuse: { value: null }, // 贴图纹理
29
+ resolution: { value: new Vector2(1 / 1024, 1 / 1024) }
30
+ },
31
+ vertexShader: `
32
+ ${ShaderChunk.common}
33
+ ${ShaderChunk.logdepthbuf_pars_vertex}
34
+ varying vec2 vUv;
35
+ void main() {
36
+ vUv = uv;
37
+ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
38
+ ${ShaderChunk.logdepthbuf_vertex}
39
+ }
40
+ `,
41
+ fragmentShader: `
42
+ ${ShaderChunk.logdepthbuf_pars_fragment}
43
+ precision highp float;
44
+
45
+ uniform sampler2D tDiffuse;
46
+
47
+ uniform vec2 resolution;
48
+
49
+ varying vec2 vUv;
50
+
51
+ #ifndef FXAA_DISCARD
52
+ //
53
+ // Only valid for PC OpenGL currently.
54
+ // Probably will not work when FXAA_GREEN_AS_LUMA = 1.
55
+ //
56
+ // 1 = Use discard on pixels which don't need AA.
57
+ // For APIs which enable concurrent TEX+ROP from same surface.
58
+ // 0 = Return unchanged color on pixels which don't need AA.
59
+ //
60
+ #define FXAA_DISCARD 0
61
+ #endif
62
+
63
+ /*--------------------------------------------------------------------------*/
64
+ #define FxaaTexTop(t, p) texture2D(t, p, -100.0)
65
+ #define FxaaTexOff(t, p, o, r) texture2D(t, p + (o * r), -100.0)
66
+ /*--------------------------------------------------------------------------*/
67
+
68
+ #define NUM_SAMPLES 5
69
+
70
+ // assumes colors have premultipliedAlpha, so that the calculated color contrast is scaled by alpha
71
+ float contrast( vec4 a, vec4 b ) {
72
+ vec4 diff = abs( a - b );
73
+ return max( max( max( diff.r, diff.g ), diff.b ), diff.a );
74
+ }
75
+
76
+ /*============================================================================
77
+
78
+ FXAA3 QUALITY - PC
79
+
80
+ ============================================================================*/
81
+
82
+ /*--------------------------------------------------------------------------*/
83
+ vec4 FxaaPixelShader(
84
+ vec2 posM,
85
+ sampler2D tex,
86
+ vec2 fxaaQualityRcpFrame,
87
+ float fxaaQualityEdgeThreshold,
88
+ float fxaaQualityinvEdgeThreshold
89
+ ) {
90
+ vec4 rgbaM = FxaaTexTop(tex, posM);
91
+ vec4 rgbaS = FxaaTexOff(tex, posM, vec2( 0.0, 1.0), fxaaQualityRcpFrame.xy);
92
+ vec4 rgbaE = FxaaTexOff(tex, posM, vec2( 1.0, 0.0), fxaaQualityRcpFrame.xy);
93
+ vec4 rgbaN = FxaaTexOff(tex, posM, vec2( 0.0,-1.0), fxaaQualityRcpFrame.xy);
94
+ vec4 rgbaW = FxaaTexOff(tex, posM, vec2(-1.0, 0.0), fxaaQualityRcpFrame.xy);
95
+ // . S .
96
+ // W M E
97
+ // . N .
98
+
99
+ bool earlyExit = max( max( max(
100
+ contrast( rgbaM, rgbaN ),
101
+ contrast( rgbaM, rgbaS ) ),
102
+ contrast( rgbaM, rgbaE ) ),
103
+ contrast( rgbaM, rgbaW ) )
104
+ < fxaaQualityEdgeThreshold;
105
+ // . 0 .
106
+ // 0 0 0
107
+ // . 0 .
108
+
109
+ #if (FXAA_DISCARD == 1)
110
+ if(earlyExit) FxaaDiscard;
111
+ #else
112
+ if(earlyExit) return rgbaM;
113
+ #endif
114
+
115
+ float contrastN = contrast( rgbaM, rgbaN );
116
+ float contrastS = contrast( rgbaM, rgbaS );
117
+ float contrastE = contrast( rgbaM, rgbaE );
118
+ float contrastW = contrast( rgbaM, rgbaW );
119
+
120
+ float relativeVContrast = ( contrastN + contrastS ) - ( contrastE + contrastW );
121
+ relativeVContrast *= fxaaQualityinvEdgeThreshold;
122
+
123
+ bool horzSpan = relativeVContrast > 0.;
124
+ // . 1 .
125
+ // 0 0 0
126
+ // . 1 .
127
+
128
+ // 45 deg edge detection and corners of objects, aka V/H contrast is too similar
129
+ if( abs( relativeVContrast ) < .3 ) {
130
+ // locate the edge
131
+ vec2 dirToEdge;
132
+ dirToEdge.x = contrastE > contrastW ? 1. : -1.;
133
+ dirToEdge.y = contrastS > contrastN ? 1. : -1.;
134
+ // . 2 . . 1 .
135
+ // 1 0 2 ~= 0 0 1
136
+ // . 1 . . 0 .
137
+
138
+ // tap 2 pixels and see which ones are "outside" the edge, to
139
+ // determine if the edge is vertical or horizontal
140
+
141
+ vec4 rgbaAlongH = FxaaTexOff(tex, posM, vec2( dirToEdge.x, -dirToEdge.y ), fxaaQualityRcpFrame.xy);
142
+ float matchAlongH = contrast( rgbaM, rgbaAlongH );
143
+ // . 1 .
144
+ // 0 0 1
145
+ // . 0 H
146
+
147
+ vec4 rgbaAlongV = FxaaTexOff(tex, posM, vec2( -dirToEdge.x, dirToEdge.y ), fxaaQualityRcpFrame.xy);
148
+ float matchAlongV = contrast( rgbaM, rgbaAlongV );
149
+ // V 1 .
150
+ // 0 0 1
151
+ // . 0 .
152
+
153
+ relativeVContrast = matchAlongV - matchAlongH;
154
+ relativeVContrast *= fxaaQualityinvEdgeThreshold;
155
+
156
+ if( abs( relativeVContrast ) < .3 ) { // 45 deg edge
157
+ // 1 1 .
158
+ // 0 0 1
159
+ // . 0 1
160
+
161
+ // do a simple blur
162
+ return mix(
163
+ rgbaM,
164
+ (rgbaN + rgbaS + rgbaE + rgbaW) * .25,
165
+ .4
166
+ );
167
+ }
168
+
169
+ horzSpan = relativeVContrast > 0.;
170
+ }
171
+
172
+ if(!horzSpan) rgbaN = rgbaW;
173
+ if(!horzSpan) rgbaS = rgbaE;
174
+ // . 0 . 1
175
+ // 1 0 1 -> 0
176
+ // . 0 . 1
177
+
178
+ bool pairN = contrast( rgbaM, rgbaN ) > contrast( rgbaM, rgbaS );
179
+ if(!pairN) rgbaN = rgbaS;
180
+
181
+ vec2 offNP;
182
+ offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
183
+ offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
184
+
185
+ bool doneN = false;
186
+ bool doneP = false;
187
+
188
+ float nDist = 0.;
189
+ float pDist = 0.;
190
+
191
+ vec2 posN = posM;
192
+ vec2 posP = posM;
193
+
194
+ int iterationsUsed = 0;
195
+ int iterationsUsedN = 0;
196
+ int iterationsUsedP = 0;
197
+ for( int i = 0; i < NUM_SAMPLES; i++ ) {
198
+ iterationsUsed = i;
199
+
200
+ float increment = float(i + 1);
201
+
202
+ if(!doneN) {
203
+ nDist += increment;
204
+ posN = posM + offNP * nDist;
205
+ vec4 rgbaEndN = FxaaTexTop(tex, posN.xy);
206
+ doneN = contrast( rgbaEndN, rgbaM ) > contrast( rgbaEndN, rgbaN );
207
+ iterationsUsedN = i;
208
+ }
209
+
210
+ if(!doneP) {
211
+ pDist += increment;
212
+ posP = posM - offNP * pDist;
213
+ vec4 rgbaEndP = FxaaTexTop(tex, posP.xy);
214
+ doneP = contrast( rgbaEndP, rgbaM ) > contrast( rgbaEndP, rgbaN );
215
+ iterationsUsedP = i;
216
+ }
217
+
218
+ if(doneN || doneP) break;
219
+ }
220
+
221
+
222
+ if ( !doneP && !doneN ) return rgbaM; // failed to find end of edge
223
+
224
+ float dist = min(
225
+ doneN ? float( iterationsUsedN ) / float( NUM_SAMPLES - 1 ) : 1.,
226
+ doneP ? float( iterationsUsedP ) / float( NUM_SAMPLES - 1 ) : 1.
227
+ );
228
+
229
+ // hacky way of reduces blurriness of mostly diagonal edges
230
+ // but reduces AA quality
231
+ dist = pow(dist, .5);
232
+
233
+ dist = 1. - dist;
234
+
235
+ return mix(
236
+ rgbaM,
237
+ rgbaN,
238
+ dist * .5
239
+ );
240
+ }
241
+
242
+ void main() {
243
+ const float edgeDetectionQuality = .2;
244
+ const float invEdgeDetectionQuality = 1. / edgeDetectionQuality;
245
+
246
+ gl_FragColor = FxaaPixelShader(
247
+ vUv,
248
+ tDiffuse,
249
+ resolution,
250
+ edgeDetectionQuality, // [0,1] contrast needed, otherwise early discard
251
+ invEdgeDetectionQuality
252
+ );
253
+ ${ShaderChunk.logdepthbuf_fragment}
254
+ }
255
+ `,
256
+ blending: NoBlending, // 渲染时不与背景融合计算 直接替换
257
+ depthTest: false,
258
+ depthWrite: false,
259
+ transparent: true
260
+ });
261
+
25
262
  // 描边着色器
26
263
  const blurShader = new RawShaderMaterial({
27
264
  uniforms: {
@@ -151,7 +388,7 @@ const scene = new Scene();
151
388
  export default function stroke_pass(renderer: WebGLRenderer, camera: Camera, object3d: Object3D) {
152
389
 
153
390
  const { stroke_enable = false, stroke_color = "#04fa12", stroke_width = 1 } = object3d.userData;
154
- if (!stroke_enable) {
391
+ if (!stroke_enable || stroke_width === 0) {
155
392
  return;
156
393
  }
157
394
 
@@ -170,6 +407,8 @@ export default function stroke_pass(renderer: WebGLRenderer, camera: Camera, obj
170
407
 
171
408
  // 设置描边着色器的分辨率
172
409
  blurShader.uniforms.resolution.value.set(1 / size.x, 1 / size.y);
410
+ // 设置抗锯齿着色器的分辨率
411
+ FXAAShaderMaterial.uniforms.resolution.value.set(1 / size.x, 1 / size.y);
173
412
  //描边颜色
174
413
  blurShader.uniforms.color.value.set(stroke_color);
175
414
  blurShader.uniforms.width.value = stroke_width / 4;
@@ -194,10 +433,15 @@ export default function stroke_pass(renderer: WebGLRenderer, camera: Camera, obj
194
433
  blurShader.uniforms.tDiffuse.value = blur1TextureTarget.texture;
195
434
  fsQuad.render(renderer, blurShader);
196
435
 
436
+ //最后抗锯齿
437
+ renderer.setRenderTarget(blur1TextureTarget);
438
+ FXAAShaderMaterial.uniforms.tDiffuse.value = blur2TextureTarget.texture;
439
+ fsQuad.render(renderer, FXAAShaderMaterial);
440
+
197
441
  // 还原帧缓冲区 减去原始纹理保留描边
198
442
  renderer.setRenderTarget(originRenderTarget);
199
443
  filterSelectShader.uniforms.selectTexture.value = selectTextureTarget.texture;
200
- filterSelectShader.uniforms.blurTexture.value = blur2TextureTarget.texture;
444
+ filterSelectShader.uniforms.blurTexture.value = blur1TextureTarget.texture;
201
445
  filterSelectShader.blending = NormalBlending; // 与有的纹理融合计算 保留前面通道传递下来的纹理
202
446
  fsQuad.render(renderer, filterSelectShader);
203
447