UNPKG

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