1- import { TempNode , MeshBasicNodeMaterial , RenderTarget , RGBAFormat , NearestFilter , QuadMesh , Vector2 } from 'three/webgpu' ;
2- import { nodeObject , vec4 , vec3 , float , modelPosition , modelWorldMatrix , passTexture , hash , Fn , wgslFn , NodeUpdateType , texture , screenUV } from 'three/tsl' ;
1+ import { TempNode , MeshBasicNodeMaterial , RenderTarget , QuadMesh , Vector2 } from 'three/webgpu' ;
2+ import { nodeObject , vec4 , vec3 , float , modelPosition , modelWorldMatrix , Fn , wgslFn , NodeUpdateType , texture , screenUV } from 'three/tsl' ;
33
44//Source: https://www.jacktollenaar.top/mesh-seam-smoothing-blending#h.50wag6hqg9gh
55
66const _size = /*@__PURE__ */ new Vector2 ( ) ;
77
88class MeshBlendNode extends TempNode {
9- constructor ( sceneOutputNode , sceneDepthNode , camera , scene ) {
10- super ( 'vec4' ) ;
11- this . sceneOutputNode = sceneOutputNode ;
12- this . sceneDepthNode = sceneDepthNode ;
13- this . updateBeforeType = NodeUpdateType . FRAME ;
14- this . renderTarget = new RenderTarget ( 1 , 1 ) ;
15- this . mainCamera = camera ;
16- this . mainScene = scene ;
17- this . blendFactor = float ( 1.2 ) ;
18- this . kernelSize = float ( 5 ) ;
19- this . kernelRadius = float ( 0.01 * this . blendFactor . value ) ;
20- this . depthFalloff = float ( 0.0001 * this . blendFactor . value ) ;
21- this . debugMaterial = new MeshBasicNodeMaterial ( ) ;
22- this . _quadMesh = new QuadMesh ( this . debugMaterial ) ;
23- }
24-
25- setup ( ) {
26- const CustomHash = wgslFn ( `
9+
10+ constructor ( sceneOutputNode , sceneDepthNode , camera , scene ) {
11+
12+ super ( 'vec4' ) ;
13+ this . sceneOutputNode = sceneOutputNode ;
14+ this . sceneDepthNode = sceneDepthNode ;
15+ this . updateBeforeType = NodeUpdateType . FRAME ;
16+ this . renderTarget = new RenderTarget ( 1 , 1 ) ;
17+ this . mainCamera = camera ;
18+ this . mainScene = scene ;
19+ this . blendFactor = float ( 1.2 ) ;
20+ this . kernelSize = float ( 5 ) ;
21+ this . kernelRadius = float ( 0.01 * this . blendFactor . value ) ;
22+ this . depthFalloff = float ( 0.0001 * this . blendFactor . value ) ;
23+ this . debugMaterial = new MeshBasicNodeMaterial ( ) ;
24+ this . _quadMesh = new QuadMesh ( this . debugMaterial ) ;
25+
26+ }
27+
28+ setup ( ) {
29+
30+ const CustomHash = wgslFn ( `
2731 fn Hash(p: vec3f) -> f32 {
2832
2933 var lp = (fract(p * 0.3183099 + 0.1));
3034 lp *= 17.0;
3135 return fract(lp.x * lp.y * lp.z * (lp.x + lp.y + lp.z));
3236 }
33- ` )
34- this . hashShader = Fn ( ( ) => {
35- let p = vec3 ( modelWorldMatrix . mul ( vec3 ( modelPosition ) ) ) . toVar ( ) ;
36- return vec4 ( CustomHash ( p ) , 0. , 0. , 1. ) ;
37- } ) ;
38- this . hashMaterial = new MeshBasicNodeMaterial ( ) ;
39- this . hashMaterial . colorNode = this . hashShader ( ) ;
40-
41- const uv = screenUV ;
42- const FinalOutputNode = Fn ( ( ) => {
43- const outputPassFunc1 = wgslFn ( `
37+ ` ) ;
38+ this . hashShader = Fn ( ( ) => {
39+
40+ const p = vec3 ( modelWorldMatrix . mul ( vec3 ( modelPosition ) ) ) . toVar ( ) ;
41+ return vec4 ( CustomHash ( p ) , 0. , 0. , 1. ) ;
42+
43+ } ) ;
44+ this . hashMaterial = new MeshBasicNodeMaterial ( ) ;
45+ this . hashMaterial . colorNode = this . hashShader ( ) ;
46+
47+ const uv = screenUV ;
48+ const FinalOutputNode = Fn ( ( ) => {
49+
50+ const outputPassFunc1 = wgslFn ( `
4451 fn OutputPassFunc1(sceneDepth: vec4<f32>, tex: texture_2d<f32>, sampler: sampler, uv: vec2f, kernelSize: f32, kernelRadius: f32, depthFalloff: f32) -> vec4<f32> {
4552 var seamLocation = vec2<f32>(0., 0.);
4653 var minDist = f32(9999999.);
@@ -64,9 +71,9 @@ class MeshBlendNode extends TempNode {
6471
6572 return vec4<f32>(seamLocation.x, seamLocation.y, minDist, 1.);
6673 }
67- ` )
74+ ` ) ;
6875
69- const finalPass = wgslFn ( `
76+ const finalPass = wgslFn ( `
7077 fn FinalPass(sceneColor: vec4f, mirroredColor: vec4f, seamLocation: vec2f, kernelRadius: f32, sceneDepth: vec4f, otherDepth: vec4f, depthFalloff: f32, minDist: f32) -> vec4f {
7178
7279 let depthDiff = abs(otherDepth.r - sceneDepth.r);
@@ -78,47 +85,56 @@ class MeshBlendNode extends TempNode {
7885
7986 return mix(sceneColor, mirroredColor, finalWeight);
8087 }
81- ` ) ;
82-
83- const pass1 = outputPassFunc1 (
84- texture ( this . sceneDepthNode , uv ) ,
85- texture ( this . renderTarget . textures [ 0 ] , uv ) ,
86- texture ( this . sceneOutputNode , uv ) ,
87- uv , this . kernelSize , this . kernelRadius , this . depthFalloff ) ;
88-
89- const mirroredColor = texture ( this . sceneOutputNode , uv . add ( pass1 . xy . mul ( 2. ) ) ) ;
90- const otherDepth = texture ( this . sceneDepthNode , uv . add ( pass1 . xy . mul ( 2. ) ) ) ;
91-
92- const sceneColor = texture ( this . sceneOutputNode , uv ) ;
93- const sceneDepth = texture ( this . sceneDepthNode , uv ) ;
94- return finalPass ( sceneColor , mirroredColor , pass1 . xy , this . kernelRadius , sceneDepth , otherDepth , this . depthFalloff , pass1 . z ) ;
95- } ) ( ) ;
96- return FinalOutputNode ;
97- }
98-
99- setSize ( width , height ) {
100- this . renderTarget . setSize ( width , height ) ;
101- }
102-
103- updateBefore ( frame ) {
104- const { renderer } = frame ;
105- const size = renderer . getSize ( _size ) ;
88+ ` ) ;
89+
90+ const pass1 = outputPassFunc1 (
91+ texture ( this . sceneDepthNode , uv ) ,
92+ texture ( this . renderTarget . textures [ 0 ] , uv ) ,
93+ texture ( this . sceneOutputNode , uv ) ,
94+ uv , this . kernelSize , this . kernelRadius , this . depthFalloff ) ;
95+
96+ const mirroredColor = texture ( this . sceneOutputNode , uv . add ( pass1 . xy . mul ( 2. ) ) ) ;
97+ const otherDepth = texture ( this . sceneDepthNode , uv . add ( pass1 . xy . mul ( 2. ) ) ) ;
98+
99+ const sceneColor = texture ( this . sceneOutputNode , uv ) ;
100+ const sceneDepth = texture ( this . sceneDepthNode , uv ) ;
101+ return finalPass ( sceneColor , mirroredColor , pass1 . xy , this . kernelRadius , sceneDepth , otherDepth , this . depthFalloff , pass1 . z ) ;
102+
103+ } ) ( ) ;
104+ return FinalOutputNode ;
105+
106+ }
107+
108+ setSize ( width , height ) {
109+
110+ this . renderTarget . setSize ( width , height ) ;
111+
112+ }
113+
114+ updateBefore ( frame ) {
115+
116+ const { renderer } = frame ;
117+ const size = renderer . getSize ( _size ) ;
106118 this . setSize ( size . width , size . height ) ;
107119
108- this . mainScene . overrideMaterial = this . hashMaterial ;
109- renderer . setRenderTarget ( this . renderTarget ) ;
110- renderer . render ( this . mainScene , this . mainCamera ) ;
120+ this . mainScene . overrideMaterial = this . hashMaterial ;
121+ renderer . setRenderTarget ( this . renderTarget ) ;
122+ renderer . render ( this . mainScene , this . mainCamera ) ;
123+
124+ this . mainScene . overrideMaterial = null ;
125+ renderer . setRenderTarget ( null ) ;
126+ this . _quadMesh . render ( renderer ) ;
127+
128+ }
129+
130+ dispose ( ) {
131+
132+ this . renderTarget . dispose ( ) ;
133+ this . hashMaterial . dispose ( ) ;
134+ this . debugMaterial . dispose ( ) ;
111135
112- this . mainScene . overrideMaterial = null ;
113- renderer . setRenderTarget ( null ) ;
114- this . _quadMesh . render ( renderer ) ;
115- }
136+ }
116137
117- dispose ( ) {
118- this . renderTarget . dispose ( ) ;
119- this . hashMaterial . dispose ( ) ;
120- this . debugMaterial . dispose ( ) ;
121- }
122138}
123139
124140export const meshblend = ( sceneOutputNode , sceneDepthNode , camera , scene ) => nodeObject ( new MeshBlendNode ( sceneOutputNode , sceneDepthNode , camera , scene ) ) ;
0 commit comments