UNPKG

19 kBJavaScriptView Raw
1( function () {
2
3 class SSRPass extends THREE.Pass {
4
5 constructor( {
6 renderer,
7 scene,
8 camera,
9 width,
10 height,
11 selects,
12 bouncing = false,
13 groundReflector
14 } ) {
15
16 super();
17 this.width = width !== undefined ? width : 512;
18 this.height = height !== undefined ? height : 512;
19 this.clear = true;
20 this.renderer = renderer;
21 this.scene = scene;
22 this.camera = camera;
23 this.groundReflector = groundReflector;
24 this.opacity = THREE.SSRShader.uniforms.opacity.value;
25 this.output = 0;
26 this.maxDistance = THREE.SSRShader.uniforms.maxDistance.value;
27 this.thickness = THREE.SSRShader.uniforms.thickness.value;
28 this.tempColor = new THREE.Color();
29 this._selects = selects;
30 this.selective = Array.isArray( this._selects );
31 Object.defineProperty( this, 'selects', {
32 get() {
33
34 return this._selects;
35
36 },
37
38 set( val ) {
39
40 if ( this._selects === val ) return;
41 this._selects = val;
42
43 if ( Array.isArray( val ) ) {
44
45 this.selective = true;
46 this.ssrMaterial.defines.SELECTIVE = true;
47 this.ssrMaterial.needsUpdate = true;
48
49 } else {
50
51 this.selective = false;
52 this.ssrMaterial.defines.SELECTIVE = false;
53 this.ssrMaterial.needsUpdate = true;
54
55 }
56
57 }
58
59 } );
60 this._bouncing = bouncing;
61 Object.defineProperty( this, 'bouncing', {
62 get() {
63
64 return this._bouncing;
65
66 },
67
68 set( val ) {
69
70 if ( this._bouncing === val ) return;
71 this._bouncing = val;
72
73 if ( val ) {
74
75 this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.prevRenderTarget.texture;
76
77 } else {
78
79 this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
80
81 }
82
83 }
84
85 } );
86 this.blur = true;
87 this._distanceAttenuation = THREE.SSRShader.defines.DISTANCE_ATTENUATION;
88 Object.defineProperty( this, 'distanceAttenuation', {
89 get() {
90
91 return this._distanceAttenuation;
92
93 },
94
95 set( val ) {
96
97 if ( this._distanceAttenuation === val ) return;
98 this._distanceAttenuation = val;
99 this.ssrMaterial.defines.DISTANCE_ATTENUATION = val;
100 this.ssrMaterial.needsUpdate = true;
101
102 }
103
104 } );
105 this._fresnel = THREE.SSRShader.defines.FRESNEL;
106 Object.defineProperty( this, 'fresnel', {
107 get() {
108
109 return this._fresnel;
110
111 },
112
113 set( val ) {
114
115 if ( this._fresnel === val ) return;
116 this._fresnel = val;
117 this.ssrMaterial.defines.FRESNEL = val;
118 this.ssrMaterial.needsUpdate = true;
119
120 }
121
122 } );
123 this._infiniteThick = THREE.SSRShader.defines.INFINITE_THICK;
124 Object.defineProperty( this, 'infiniteThick', {
125 get() {
126
127 return this._infiniteThick;
128
129 },
130
131 set( val ) {
132
133 if ( this._infiniteThick === val ) return;
134 this._infiniteThick = val;
135 this.ssrMaterial.defines.INFINITE_THICK = val;
136 this.ssrMaterial.needsUpdate = true;
137
138 }
139
140 } ); // beauty render target with depth buffer
141
142 const depthTexture = new THREE.DepthTexture();
143 depthTexture.type = THREE.UnsignedShortType;
144 depthTexture.minFilter = THREE.NearestFilter;
145 depthTexture.magFilter = THREE.NearestFilter;
146 this.beautyRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, {
147 minFilter: THREE.NearestFilter,
148 magFilter: THREE.NearestFilter,
149 format: THREE.RGBAFormat,
150 depthTexture: depthTexture,
151 depthBuffer: true
152 } ); //for bouncing
153
154 this.prevRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, {
155 minFilter: THREE.NearestFilter,
156 magFilter: THREE.NearestFilter,
157 format: THREE.RGBAFormat
158 } ); // normal render target
159
160 this.normalRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, {
161 minFilter: THREE.NearestFilter,
162 magFilter: THREE.NearestFilter,
163 format: THREE.RGBAFormat,
164 type: THREE.HalfFloatType
165 } ); // metalness render target
166
167 this.metalnessRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, {
168 minFilter: THREE.NearestFilter,
169 magFilter: THREE.NearestFilter,
170 format: THREE.RGBAFormat
171 } ); // ssr render target
172
173 this.ssrRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, {
174 minFilter: THREE.NearestFilter,
175 magFilter: THREE.NearestFilter,
176 format: THREE.RGBAFormat
177 } );
178 this.blurRenderTarget = this.ssrRenderTarget.clone();
179 this.blurRenderTarget2 = this.ssrRenderTarget.clone(); // this.blurRenderTarget3 = this.ssrRenderTarget.clone();
180 // ssr material
181
182 if ( THREE.SSRShader === undefined ) {
183
184 console.error( 'THREE.SSRPass: The pass relies on THREE.SSRShader.' );
185
186 }
187
188 this.ssrMaterial = new THREE.ShaderMaterial( {
189 defines: Object.assign( {}, THREE.SSRShader.defines, {
190 MAX_STEP: Math.sqrt( this.width * this.width + this.height * this.height )
191 } ),
192 uniforms: THREE.UniformsUtils.clone( THREE.SSRShader.uniforms ),
193 vertexShader: THREE.SSRShader.vertexShader,
194 fragmentShader: THREE.SSRShader.fragmentShader,
195 blending: THREE.NoBlending
196 } );
197 this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
198 this.ssrMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture;
199 this.ssrMaterial.defines.SELECTIVE = this.selective;
200 this.ssrMaterial.needsUpdate = true;
201 this.ssrMaterial.uniforms[ 'tMetalness' ].value = this.metalnessRenderTarget.texture;
202 this.ssrMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture;
203 this.ssrMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
204 this.ssrMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
205 this.ssrMaterial.uniforms[ 'thickness' ].value = this.thickness;
206 this.ssrMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );
207 this.ssrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
208 this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); // normal material
209
210 this.normalMaterial = new THREE.MeshNormalMaterial();
211 this.normalMaterial.blending = THREE.NoBlending; // metalnessOn material
212
213 this.metalnessOnMaterial = new THREE.MeshBasicMaterial( {
214 color: 'white'
215 } ); // metalnessOff material
216
217 this.metalnessOffMaterial = new THREE.MeshBasicMaterial( {
218 color: 'black'
219 } ); // blur material
220
221 this.blurMaterial = new THREE.ShaderMaterial( {
222 defines: Object.assign( {}, THREE.SSRBlurShader.defines ),
223 uniforms: THREE.UniformsUtils.clone( THREE.SSRBlurShader.uniforms ),
224 vertexShader: THREE.SSRBlurShader.vertexShader,
225 fragmentShader: THREE.SSRBlurShader.fragmentShader
226 } );
227 this.blurMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
228 this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); // blur material 2
229
230 this.blurMaterial2 = new THREE.ShaderMaterial( {
231 defines: Object.assign( {}, THREE.SSRBlurShader.defines ),
232 uniforms: THREE.UniformsUtils.clone( THREE.SSRBlurShader.uniforms ),
233 vertexShader: THREE.SSRBlurShader.vertexShader,
234 fragmentShader: THREE.SSRBlurShader.fragmentShader
235 } );
236 this.blurMaterial2.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture;
237 this.blurMaterial2.uniforms[ 'resolution' ].value.set( this.width, this.height ); // // blur material 3
238 // this.blurMaterial3 = new THREE.ShaderMaterial({
239 // defines: Object.assign({}, THREE.SSRBlurShader.defines),
240 // uniforms: THREE.UniformsUtils.clone(THREE.SSRBlurShader.uniforms),
241 // vertexShader: THREE.SSRBlurShader.vertexShader,
242 // fragmentShader: THREE.SSRBlurShader.fragmentShader
243 // });
244 // this.blurMaterial3.uniforms['tDiffuse'].value = this.blurRenderTarget2.texture;
245 // this.blurMaterial3.uniforms['resolution'].value.set(this.width, this.height);
246 // material for rendering the depth
247
248 this.depthRenderMaterial = new THREE.ShaderMaterial( {
249 defines: Object.assign( {}, THREE.SSRDepthShader.defines ),
250 uniforms: THREE.UniformsUtils.clone( THREE.SSRDepthShader.uniforms ),
251 vertexShader: THREE.SSRDepthShader.vertexShader,
252 fragmentShader: THREE.SSRDepthShader.fragmentShader,
253 blending: THREE.NoBlending
254 } );
255 this.depthRenderMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture;
256 this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
257 this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; // material for rendering the content of a render target
258
259 this.copyMaterial = new THREE.ShaderMaterial( {
260 uniforms: THREE.UniformsUtils.clone( THREE.CopyShader.uniforms ),
261 vertexShader: THREE.CopyShader.vertexShader,
262 fragmentShader: THREE.CopyShader.fragmentShader,
263 transparent: true,
264 depthTest: false,
265 depthWrite: false,
266 blendSrc: THREE.SrcAlphaFactor,
267 blendDst: THREE.OneMinusSrcAlphaFactor,
268 blendEquation: THREE.AddEquation,
269 blendSrcAlpha: THREE.SrcAlphaFactor,
270 blendDstAlpha: THREE.OneMinusSrcAlphaFactor,
271 blendEquationAlpha: THREE.AddEquation // premultipliedAlpha:true,
272
273 } );
274 this.fsQuad = new THREE.FullScreenQuad( null );
275 this.originalClearColor = new THREE.Color();
276
277 }
278
279 dispose() {
280
281 // dispose render targets
282 this.beautyRenderTarget.dispose();
283 this.prevRenderTarget.dispose();
284 this.normalRenderTarget.dispose();
285 this.metalnessRenderTarget.dispose();
286 this.ssrRenderTarget.dispose();
287 this.blurRenderTarget.dispose();
288 this.blurRenderTarget2.dispose(); // this.blurRenderTarget3.dispose();
289 // dispose materials
290
291 this.normalMaterial.dispose();
292 this.metalnessOnMaterial.dispose();
293 this.metalnessOffMaterial.dispose();
294 this.blurMaterial.dispose();
295 this.blurMaterial2.dispose();
296 this.copyMaterial.dispose();
297 this.depthRenderMaterial.dispose(); // dipsose full screen quad
298
299 this.fsQuad.dispose();
300
301 }
302
303 render( renderer, writeBuffer
304 /*, readBuffer, deltaTime, maskActive */
305 ) {
306
307 // render beauty and depth
308 renderer.setRenderTarget( this.beautyRenderTarget );
309 renderer.clear();
310
311 if ( this.groundReflector ) {
312
313 this.groundReflector.visible = false;
314 this.groundReflector.doRender( this.renderer, this.scene, this.camera );
315 this.groundReflector.visible = true;
316
317 }
318
319 renderer.render( this.scene, this.camera );
320 if ( this.groundReflector ) this.groundReflector.visible = false; // render normals
321
322 this.renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0, 0 ); // render metalnesses
323
324 if ( this.selective ) {
325
326 this.renderMetalness( renderer, this.metalnessOnMaterial, this.metalnessRenderTarget, 0, 0 );
327
328 } // render SSR
329
330
331 this.ssrMaterial.uniforms[ 'opacity' ].value = this.opacity;
332 this.ssrMaterial.uniforms[ 'maxDistance' ].value = this.maxDistance;
333 this.ssrMaterial.uniforms[ 'thickness' ].value = this.thickness;
334 this.renderPass( renderer, this.ssrMaterial, this.ssrRenderTarget ); // render blur
335
336 if ( this.blur ) {
337
338 this.renderPass( renderer, this.blurMaterial, this.blurRenderTarget );
339 this.renderPass( renderer, this.blurMaterial2, this.blurRenderTarget2 ); // this.renderPass(renderer, this.blurMaterial3, this.blurRenderTarget3);
340
341 } // output result to screen
342
343
344 switch ( this.output ) {
345
346 case SSRPass.OUTPUT.Default:
347 if ( this.bouncing ) {
348
349 this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
350 this.copyMaterial.blending = THREE.NoBlending;
351 this.renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
352 if ( this.blur ) this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture; else this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
353 this.copyMaterial.blending = THREE.NormalBlending;
354 this.renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
355 this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.prevRenderTarget.texture;
356 this.copyMaterial.blending = THREE.NoBlending;
357 this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
358
359 } else {
360
361 this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
362 this.copyMaterial.blending = THREE.NoBlending;
363 this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
364 if ( this.blur ) this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture; else this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
365 this.copyMaterial.blending = THREE.NormalBlending;
366 this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
367
368 }
369
370 break;
371
372 case SSRPass.OUTPUT.SSR:
373 if ( this.blur ) this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture; else this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
374 this.copyMaterial.blending = THREE.NoBlending;
375 this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
376
377 if ( this.bouncing ) {
378
379 if ( this.blur ) this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture; else this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
380 this.copyMaterial.blending = THREE.NoBlending;
381 this.renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
382 this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
383 this.copyMaterial.blending = THREE.NormalBlending;
384 this.renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
385
386 }
387
388 break;
389
390 case SSRPass.OUTPUT.Beauty:
391 this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
392 this.copyMaterial.blending = THREE.NoBlending;
393 this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
394 break;
395
396 case SSRPass.OUTPUT.Depth:
397 this.renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : writeBuffer );
398 break;
399
400 case SSRPass.OUTPUT.Normal:
401 this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.normalRenderTarget.texture;
402 this.copyMaterial.blending = THREE.NoBlending;
403 this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
404 break;
405
406 case SSRPass.OUTPUT.Metalness:
407 this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.metalnessRenderTarget.texture;
408 this.copyMaterial.blending = THREE.NoBlending;
409 this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
410 break;
411
412 default:
413 console.warn( 'THREE.SSRPass: Unknown output type.' );
414
415 }
416
417 }
418
419 renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
420
421 // save original state
422 this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) );
423 const originalClearAlpha = renderer.getClearAlpha( this.tempColor );
424 const originalAutoClear = renderer.autoClear;
425 renderer.setRenderTarget( renderTarget ); // setup pass state
426
427 renderer.autoClear = false;
428
429 if ( clearColor !== undefined && clearColor !== null ) {
430
431 renderer.setClearColor( clearColor );
432 renderer.setClearAlpha( clearAlpha || 0.0 );
433 renderer.clear();
434
435 }
436
437 this.fsQuad.material = passMaterial;
438 this.fsQuad.render( renderer ); // restore original state
439
440 renderer.autoClear = originalAutoClear;
441 renderer.setClearColor( this.originalClearColor );
442 renderer.setClearAlpha( originalClearAlpha );
443
444 }
445
446 renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
447
448 this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) );
449 const originalClearAlpha = renderer.getClearAlpha( this.tempColor );
450 const originalAutoClear = renderer.autoClear;
451 renderer.setRenderTarget( renderTarget );
452 renderer.autoClear = false;
453 clearColor = overrideMaterial.clearColor || clearColor;
454 clearAlpha = overrideMaterial.clearAlpha || clearAlpha;
455
456 if ( clearColor !== undefined && clearColor !== null ) {
457
458 renderer.setClearColor( clearColor );
459 renderer.setClearAlpha( clearAlpha || 0.0 );
460 renderer.clear();
461
462 }
463
464 this.scene.overrideMaterial = overrideMaterial;
465 renderer.render( this.scene, this.camera );
466 this.scene.overrideMaterial = null; // restore original state
467
468 renderer.autoClear = originalAutoClear;
469 renderer.setClearColor( this.originalClearColor );
470 renderer.setClearAlpha( originalClearAlpha );
471
472 }
473
474 renderMetalness( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
475
476 this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) );
477 const originalClearAlpha = renderer.getClearAlpha( this.tempColor );
478 const originalAutoClear = renderer.autoClear;
479 renderer.setRenderTarget( renderTarget );
480 renderer.autoClear = false;
481 clearColor = overrideMaterial.clearColor || clearColor;
482 clearAlpha = overrideMaterial.clearAlpha || clearAlpha;
483
484 if ( clearColor !== undefined && clearColor !== null ) {
485
486 renderer.setClearColor( clearColor );
487 renderer.setClearAlpha( clearAlpha || 0.0 );
488 renderer.clear();
489
490 }
491
492 this.scene.traverseVisible( child => {
493
494 child._SSRPassBackupMaterial = child.material;
495
496 if ( this._selects.includes( child ) ) {
497
498 child.material = this.metalnessOnMaterial;
499
500 } else {
501
502 child.material = this.metalnessOffMaterial;
503
504 }
505
506 } );
507 renderer.render( this.scene, this.camera );
508 this.scene.traverseVisible( child => {
509
510 child.material = child._SSRPassBackupMaterial;
511
512 } ); // restore original state
513
514 renderer.autoClear = originalAutoClear;
515 renderer.setClearColor( this.originalClearColor );
516 renderer.setClearAlpha( originalClearAlpha );
517
518 }
519
520 setSize( width, height ) {
521
522 this.width = width;
523 this.height = height;
524 this.ssrMaterial.defines.MAX_STEP = Math.sqrt( width * width + height * height );
525 this.ssrMaterial.needsUpdate = true;
526 this.beautyRenderTarget.setSize( width, height );
527 this.prevRenderTarget.setSize( width, height );
528 this.ssrRenderTarget.setSize( width, height );
529 this.normalRenderTarget.setSize( width, height );
530 this.metalnessRenderTarget.setSize( width, height );
531 this.blurRenderTarget.setSize( width, height );
532 this.blurRenderTarget2.setSize( width, height ); // this.blurRenderTarget3.setSize(width, height);
533
534 this.ssrMaterial.uniforms[ 'resolution' ].value.set( width, height );
535 this.ssrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
536 this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
537 this.blurMaterial.uniforms[ 'resolution' ].value.set( width, height );
538 this.blurMaterial2.uniforms[ 'resolution' ].value.set( width, height );
539
540 }
541
542 }
543
544 SSRPass.OUTPUT = {
545 'Default': 0,
546 'SSR': 1,
547 'Beauty': 3,
548 'Depth': 4,
549 'Normal': 5,
550 'Metalness': 7
551 };
552
553 THREE.SSRPass = SSRPass;
554
555} )();