SSRPass.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. import {
  2. AddEquation,
  3. Color,
  4. NormalBlending,
  5. DepthTexture,
  6. SrcAlphaFactor,
  7. OneMinusSrcAlphaFactor,
  8. MeshNormalMaterial,
  9. MeshBasicMaterial,
  10. NearestFilter,
  11. NoBlending,
  12. ShaderMaterial,
  13. UniformsUtils,
  14. UnsignedShortType,
  15. WebGLRenderTarget,
  16. HalfFloatType,
  17. } from 'three';
  18. import { Pass, FullScreenQuad } from './Pass.js';
  19. import { SSRBlurShader, SSRDepthShader, SSRShader } from '../shaders/SSRShader.js';
  20. import { CopyShader } from '../shaders/CopyShader.js';
  21. /**
  22. * A pass for a basic SSR effect.
  23. *
  24. * ```js
  25. * const ssrPass = new SSRPass( {
  26. * renderer,
  27. * scene,
  28. * camera,
  29. * width: innerWidth,
  30. * height: innerHeight
  31. * } );
  32. * composer.addPass( ssrPass );
  33. * ```
  34. *
  35. * @augments Pass
  36. * @three_import import { SSRPass } from 'three/addons/postprocessing/SSRPass.js';
  37. */
  38. class SSRPass extends Pass {
  39. /**
  40. * Constructs a new SSR pass.
  41. *
  42. * @param {SSRPass~Options} options - The pass options.
  43. */
  44. constructor( { renderer, scene, camera, width = 512, height = 512, selects = null, bouncing = false, groundReflector = null } ) {
  45. super();
  46. /**
  47. * The width of the effect.
  48. *
  49. * @type {number}
  50. * @default 512
  51. */
  52. this.width = width;
  53. /**
  54. * The height of the effect.
  55. *
  56. * @type {number}
  57. * @default 512
  58. */
  59. this.height = height;
  60. /**
  61. * Overwritten to perform a clear operation by default.
  62. *
  63. * @type {boolean}
  64. * @default true
  65. */
  66. this.clear = true;
  67. /**
  68. * The renderer.
  69. *
  70. * @type {WebGLRenderer}
  71. */
  72. this.renderer = renderer;
  73. /**
  74. * The scene to render.
  75. *
  76. * @type {Scene}
  77. */
  78. this.scene = scene;
  79. /**
  80. * The camera.
  81. *
  82. * @type {Camera}
  83. */
  84. this.camera = camera;
  85. /**
  86. * The ground reflector.
  87. *
  88. * @type {?ReflectorForSSRPass}
  89. * @default 0
  90. */
  91. this.groundReflector = groundReflector;
  92. /**
  93. * The opacity.
  94. *
  95. * @type {number}
  96. * @default 0.5
  97. */
  98. this.opacity = SSRShader.uniforms.opacity.value;
  99. /**
  100. * The output configuration.
  101. *
  102. * @type {number}
  103. * @default 0
  104. */
  105. this.output = 0;
  106. /**
  107. * Controls how far a fragment can reflect.
  108. *
  109. * @type {number}
  110. * @default 180
  111. */
  112. this.maxDistance = SSRShader.uniforms.maxDistance.value;
  113. /**
  114. * Controls the cutoff between what counts as a
  115. * possible reflection hit and what does not.
  116. *
  117. * @type {number}
  118. * @default .018
  119. */
  120. this.thickness = SSRShader.uniforms.thickness.value;
  121. this.tempColor = new Color();
  122. this._selects = selects;
  123. /**
  124. * Whether the pass is selective or not.
  125. *
  126. * @type {boolean}
  127. * @default false
  128. */
  129. this.selective = Array.isArray( this._selects );
  130. /**
  131. * Which 3D objects should be affected by SSR. If not set, the entire scene is affected.
  132. *
  133. * @name SSRPass#selects
  134. * @type {?Array<Object3D>}
  135. * @default null
  136. */
  137. Object.defineProperty( this, 'selects', {
  138. get() {
  139. return this._selects;
  140. },
  141. set( val ) {
  142. if ( this._selects === val ) return;
  143. this._selects = val;
  144. if ( Array.isArray( val ) ) {
  145. this.selective = true;
  146. this.ssrMaterial.defines.SELECTIVE = true;
  147. this.ssrMaterial.needsUpdate = true;
  148. } else {
  149. this.selective = false;
  150. this.ssrMaterial.defines.SELECTIVE = false;
  151. this.ssrMaterial.needsUpdate = true;
  152. }
  153. }
  154. } );
  155. this._bouncing = bouncing;
  156. /**
  157. * Whether bouncing is enabled or not.
  158. *
  159. * @name SSRPass#bouncing
  160. * @type {boolean}
  161. * @default false
  162. */
  163. Object.defineProperty( this, 'bouncing', {
  164. get() {
  165. return this._bouncing;
  166. },
  167. set( val ) {
  168. if ( this._bouncing === val ) return;
  169. this._bouncing = val;
  170. if ( val ) {
  171. this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.prevRenderTarget.texture;
  172. } else {
  173. this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
  174. }
  175. }
  176. } );
  177. /**
  178. * Whether to blur reflections or not.
  179. *
  180. * @type {boolean}
  181. * @default true
  182. */
  183. this.blur = true;
  184. this._distanceAttenuation = SSRShader.defines.DISTANCE_ATTENUATION;
  185. /**
  186. * Whether to use distance attenuation or not.
  187. *
  188. * @name SSRPass#distanceAttenuation
  189. * @type {boolean}
  190. * @default true
  191. */
  192. Object.defineProperty( this, 'distanceAttenuation', {
  193. get() {
  194. return this._distanceAttenuation;
  195. },
  196. set( val ) {
  197. if ( this._distanceAttenuation === val ) return;
  198. this._distanceAttenuation = val;
  199. this.ssrMaterial.defines.DISTANCE_ATTENUATION = val;
  200. this.ssrMaterial.needsUpdate = true;
  201. }
  202. } );
  203. this._fresnel = SSRShader.defines.FRESNEL;
  204. /**
  205. * Whether to use fresnel or not.
  206. *
  207. * @name SSRPass#fresnel
  208. * @type {boolean}
  209. * @default true
  210. */
  211. Object.defineProperty( this, 'fresnel', {
  212. get() {
  213. return this._fresnel;
  214. },
  215. set( val ) {
  216. if ( this._fresnel === val ) return;
  217. this._fresnel = val;
  218. this.ssrMaterial.defines.FRESNEL = val;
  219. this.ssrMaterial.needsUpdate = true;
  220. }
  221. } );
  222. this._infiniteThick = SSRShader.defines.INFINITE_THICK;
  223. /**
  224. * Whether to use infinite thickness or not.
  225. *
  226. * @name SSRPass#infiniteThick
  227. * @type {boolean}
  228. * @default false
  229. */
  230. Object.defineProperty( this, 'infiniteThick', {
  231. get() {
  232. return this._infiniteThick;
  233. },
  234. set( val ) {
  235. if ( this._infiniteThick === val ) return;
  236. this._infiniteThick = val;
  237. this.ssrMaterial.defines.INFINITE_THICK = val;
  238. this.ssrMaterial.needsUpdate = true;
  239. }
  240. } );
  241. // beauty render target with depth buffer
  242. const depthTexture = new DepthTexture();
  243. depthTexture.type = UnsignedShortType;
  244. depthTexture.minFilter = NearestFilter;
  245. depthTexture.magFilter = NearestFilter;
  246. this.beautyRenderTarget = new WebGLRenderTarget( this.width, this.height, {
  247. minFilter: NearestFilter,
  248. magFilter: NearestFilter,
  249. type: HalfFloatType,
  250. depthTexture: depthTexture,
  251. depthBuffer: true
  252. } );
  253. //for bouncing
  254. this.prevRenderTarget = new WebGLRenderTarget( this.width, this.height, {
  255. minFilter: NearestFilter,
  256. magFilter: NearestFilter
  257. } );
  258. // normal render target
  259. this.normalRenderTarget = new WebGLRenderTarget( this.width, this.height, {
  260. minFilter: NearestFilter,
  261. magFilter: NearestFilter,
  262. type: HalfFloatType,
  263. } );
  264. // metalness render target
  265. this.metalnessRenderTarget = new WebGLRenderTarget( this.width, this.height, {
  266. minFilter: NearestFilter,
  267. magFilter: NearestFilter,
  268. type: HalfFloatType,
  269. } );
  270. // ssr render target
  271. this.ssrRenderTarget = new WebGLRenderTarget( this.width, this.height, {
  272. minFilter: NearestFilter,
  273. magFilter: NearestFilter
  274. } );
  275. this.blurRenderTarget = this.ssrRenderTarget.clone();
  276. this.blurRenderTarget2 = this.ssrRenderTarget.clone();
  277. // this.blurRenderTarget3 = this.ssrRenderTarget.clone();
  278. // ssr material
  279. this.ssrMaterial = new ShaderMaterial( {
  280. defines: Object.assign( {}, SSRShader.defines, {
  281. MAX_STEP: Math.sqrt( this.width * this.width + this.height * this.height )
  282. } ),
  283. uniforms: UniformsUtils.clone( SSRShader.uniforms ),
  284. vertexShader: SSRShader.vertexShader,
  285. fragmentShader: SSRShader.fragmentShader,
  286. blending: NoBlending
  287. } );
  288. this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
  289. this.ssrMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture;
  290. this.ssrMaterial.defines.SELECTIVE = this.selective;
  291. this.ssrMaterial.needsUpdate = true;
  292. this.ssrMaterial.uniforms[ 'tMetalness' ].value = this.metalnessRenderTarget.texture;
  293. this.ssrMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture;
  294. this.ssrMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
  295. this.ssrMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
  296. this.ssrMaterial.uniforms[ 'thickness' ].value = this.thickness;
  297. this.ssrMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );
  298. this.ssrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
  299. this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
  300. // normal material
  301. this.normalMaterial = new MeshNormalMaterial();
  302. this.normalMaterial.blending = NoBlending;
  303. // metalnessOn material
  304. this.metalnessOnMaterial = new MeshBasicMaterial( {
  305. color: 'white'
  306. } );
  307. // metalnessOff material
  308. this.metalnessOffMaterial = new MeshBasicMaterial( {
  309. color: 'black'
  310. } );
  311. // blur material
  312. this.blurMaterial = new ShaderMaterial( {
  313. defines: Object.assign( {}, SSRBlurShader.defines ),
  314. uniforms: UniformsUtils.clone( SSRBlurShader.uniforms ),
  315. vertexShader: SSRBlurShader.vertexShader,
  316. fragmentShader: SSRBlurShader.fragmentShader
  317. } );
  318. this.blurMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
  319. this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );
  320. // blur material 2
  321. this.blurMaterial2 = new ShaderMaterial( {
  322. defines: Object.assign( {}, SSRBlurShader.defines ),
  323. uniforms: UniformsUtils.clone( SSRBlurShader.uniforms ),
  324. vertexShader: SSRBlurShader.vertexShader,
  325. fragmentShader: SSRBlurShader.fragmentShader
  326. } );
  327. this.blurMaterial2.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture;
  328. this.blurMaterial2.uniforms[ 'resolution' ].value.set( this.width, this.height );
  329. // // blur material 3
  330. // this.blurMaterial3 = new ShaderMaterial({
  331. // defines: Object.assign({}, SSRBlurShader.defines),
  332. // uniforms: UniformsUtils.clone(SSRBlurShader.uniforms),
  333. // vertexShader: SSRBlurShader.vertexShader,
  334. // fragmentShader: SSRBlurShader.fragmentShader
  335. // });
  336. // this.blurMaterial3.uniforms['tDiffuse'].value = this.blurRenderTarget2.texture;
  337. // this.blurMaterial3.uniforms['resolution'].value.set(this.width, this.height);
  338. // material for rendering the depth
  339. this.depthRenderMaterial = new ShaderMaterial( {
  340. defines: Object.assign( {}, SSRDepthShader.defines ),
  341. uniforms: UniformsUtils.clone( SSRDepthShader.uniforms ),
  342. vertexShader: SSRDepthShader.vertexShader,
  343. fragmentShader: SSRDepthShader.fragmentShader,
  344. blending: NoBlending
  345. } );
  346. this.depthRenderMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture;
  347. this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
  348. this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
  349. // material for rendering the content of a render target
  350. this.copyMaterial = new ShaderMaterial( {
  351. uniforms: UniformsUtils.clone( CopyShader.uniforms ),
  352. vertexShader: CopyShader.vertexShader,
  353. fragmentShader: CopyShader.fragmentShader,
  354. transparent: true,
  355. depthTest: false,
  356. depthWrite: false,
  357. blendSrc: SrcAlphaFactor,
  358. blendDst: OneMinusSrcAlphaFactor,
  359. blendEquation: AddEquation,
  360. blendSrcAlpha: SrcAlphaFactor,
  361. blendDstAlpha: OneMinusSrcAlphaFactor,
  362. blendEquationAlpha: AddEquation,
  363. // premultipliedAlpha:true,
  364. } );
  365. this.fsQuad = new FullScreenQuad( null );
  366. this.originalClearColor = new Color();
  367. }
  368. /**
  369. * Frees the GPU-related resources allocated by this instance. Call this
  370. * method whenever the pass is no longer used in your app.
  371. */
  372. dispose() {
  373. // dispose render targets
  374. this.beautyRenderTarget.dispose();
  375. this.prevRenderTarget.dispose();
  376. this.normalRenderTarget.dispose();
  377. this.metalnessRenderTarget.dispose();
  378. this.ssrRenderTarget.dispose();
  379. this.blurRenderTarget.dispose();
  380. this.blurRenderTarget2.dispose();
  381. // this.blurRenderTarget3.dispose();
  382. // dispose materials
  383. this.normalMaterial.dispose();
  384. this.metalnessOnMaterial.dispose();
  385. this.metalnessOffMaterial.dispose();
  386. this.blurMaterial.dispose();
  387. this.blurMaterial2.dispose();
  388. this.copyMaterial.dispose();
  389. this.depthRenderMaterial.dispose();
  390. // dispose full screen quad
  391. this.fsQuad.dispose();
  392. }
  393. /**
  394. * Performs the SSR pass.
  395. *
  396. * @param {WebGLRenderer} renderer - The renderer.
  397. * @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
  398. * destination for the pass.
  399. * @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
  400. * previous pass from this buffer.
  401. * @param {number} deltaTime - The delta time in seconds.
  402. * @param {boolean} maskActive - Whether masking is active or not.
  403. */
  404. render( renderer, writeBuffer /*, readBuffer, deltaTime, maskActive */ ) {
  405. // render beauty and depth
  406. renderer.setRenderTarget( this.beautyRenderTarget );
  407. renderer.clear();
  408. if ( this.groundReflector ) {
  409. this.groundReflector.visible = false;
  410. this.groundReflector.doRender( this.renderer, this.scene, this.camera );
  411. this.groundReflector.visible = true;
  412. }
  413. renderer.render( this.scene, this.camera );
  414. if ( this.groundReflector ) this.groundReflector.visible = false;
  415. // render normals
  416. this._renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0, 0 );
  417. // render metalnesses
  418. if ( this.selective ) {
  419. this._renderMetalness( renderer, this.metalnessOnMaterial, this.metalnessRenderTarget, 0, 0 );
  420. }
  421. // render SSR
  422. this.ssrMaterial.uniforms[ 'opacity' ].value = this.opacity;
  423. this.ssrMaterial.uniforms[ 'maxDistance' ].value = this.maxDistance;
  424. this.ssrMaterial.uniforms[ 'thickness' ].value = this.thickness;
  425. this._renderPass( renderer, this.ssrMaterial, this.ssrRenderTarget );
  426. // render blur
  427. if ( this.blur ) {
  428. this._renderPass( renderer, this.blurMaterial, this.blurRenderTarget );
  429. this._renderPass( renderer, this.blurMaterial2, this.blurRenderTarget2 );
  430. // this._renderPass(renderer, this.blurMaterial3, this.blurRenderTarget3);
  431. }
  432. // output result to screen
  433. switch ( this.output ) {
  434. case SSRPass.OUTPUT.Default:
  435. if ( this.bouncing ) {
  436. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
  437. this.copyMaterial.blending = NoBlending;
  438. this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
  439. if ( this.blur )
  440. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture;
  441. else
  442. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
  443. this.copyMaterial.blending = NormalBlending;
  444. this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
  445. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.prevRenderTarget.texture;
  446. this.copyMaterial.blending = NoBlending;
  447. this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
  448. } else {
  449. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
  450. this.copyMaterial.blending = NoBlending;
  451. this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
  452. if ( this.blur )
  453. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture;
  454. else
  455. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
  456. this.copyMaterial.blending = NormalBlending;
  457. this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
  458. }
  459. break;
  460. case SSRPass.OUTPUT.SSR:
  461. if ( this.blur )
  462. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture;
  463. else
  464. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
  465. this.copyMaterial.blending = NoBlending;
  466. this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
  467. if ( this.bouncing ) {
  468. if ( this.blur )
  469. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture;
  470. else
  471. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
  472. this.copyMaterial.blending = NoBlending;
  473. this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
  474. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
  475. this.copyMaterial.blending = NormalBlending;
  476. this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
  477. }
  478. break;
  479. case SSRPass.OUTPUT.Beauty:
  480. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
  481. this.copyMaterial.blending = NoBlending;
  482. this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
  483. break;
  484. case SSRPass.OUTPUT.Depth:
  485. this._renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : writeBuffer );
  486. break;
  487. case SSRPass.OUTPUT.Normal:
  488. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.normalRenderTarget.texture;
  489. this.copyMaterial.blending = NoBlending;
  490. this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
  491. break;
  492. case SSRPass.OUTPUT.Metalness:
  493. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.metalnessRenderTarget.texture;
  494. this.copyMaterial.blending = NoBlending;
  495. this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
  496. break;
  497. default:
  498. console.warn( 'THREE.SSRPass: Unknown output type.' );
  499. }
  500. }
  501. /**
  502. * Sets the size of the pass.
  503. *
  504. * @param {number} width - The width to set.
  505. * @param {number} height - The width to set.
  506. */
  507. setSize( width, height ) {
  508. this.width = width;
  509. this.height = height;
  510. this.ssrMaterial.defines.MAX_STEP = Math.sqrt( width * width + height * height );
  511. this.ssrMaterial.needsUpdate = true;
  512. this.beautyRenderTarget.setSize( width, height );
  513. this.prevRenderTarget.setSize( width, height );
  514. this.ssrRenderTarget.setSize( width, height );
  515. this.normalRenderTarget.setSize( width, height );
  516. this.metalnessRenderTarget.setSize( width, height );
  517. this.blurRenderTarget.setSize( width, height );
  518. this.blurRenderTarget2.setSize( width, height );
  519. // this.blurRenderTarget3.setSize(width, height);
  520. this.ssrMaterial.uniforms[ 'resolution' ].value.set( width, height );
  521. this.ssrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
  522. this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
  523. this.blurMaterial.uniforms[ 'resolution' ].value.set( width, height );
  524. this.blurMaterial2.uniforms[ 'resolution' ].value.set( width, height );
  525. }
  526. // internals
  527. _renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
  528. // save original state
  529. this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) );
  530. const originalClearAlpha = renderer.getClearAlpha( this.tempColor );
  531. const originalAutoClear = renderer.autoClear;
  532. renderer.setRenderTarget( renderTarget );
  533. // setup pass state
  534. renderer.autoClear = false;
  535. if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
  536. renderer.setClearColor( clearColor );
  537. renderer.setClearAlpha( clearAlpha || 0.0 );
  538. renderer.clear();
  539. }
  540. this.fsQuad.material = passMaterial;
  541. this.fsQuad.render( renderer );
  542. // restore original state
  543. renderer.autoClear = originalAutoClear;
  544. renderer.setClearColor( this.originalClearColor );
  545. renderer.setClearAlpha( originalClearAlpha );
  546. }
  547. _renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
  548. this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) );
  549. const originalClearAlpha = renderer.getClearAlpha( this.tempColor );
  550. const originalAutoClear = renderer.autoClear;
  551. renderer.setRenderTarget( renderTarget );
  552. renderer.autoClear = false;
  553. clearColor = overrideMaterial.clearColor || clearColor;
  554. clearAlpha = overrideMaterial.clearAlpha || clearAlpha;
  555. if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
  556. renderer.setClearColor( clearColor );
  557. renderer.setClearAlpha( clearAlpha || 0.0 );
  558. renderer.clear();
  559. }
  560. this.scene.overrideMaterial = overrideMaterial;
  561. renderer.render( this.scene, this.camera );
  562. this.scene.overrideMaterial = null;
  563. // restore original state
  564. renderer.autoClear = originalAutoClear;
  565. renderer.setClearColor( this.originalClearColor );
  566. renderer.setClearAlpha( originalClearAlpha );
  567. }
  568. _renderMetalness( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
  569. this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) );
  570. const originalClearAlpha = renderer.getClearAlpha( this.tempColor );
  571. const originalAutoClear = renderer.autoClear;
  572. const originalBackground = this.scene.background;
  573. const originalFog = this.scene.fog;
  574. renderer.setRenderTarget( renderTarget );
  575. renderer.autoClear = false;
  576. this.scene.background = null;
  577. this.scene.fog = null;
  578. clearColor = overrideMaterial.clearColor || clearColor;
  579. clearAlpha = overrideMaterial.clearAlpha || clearAlpha;
  580. if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
  581. renderer.setClearColor( clearColor );
  582. renderer.setClearAlpha( clearAlpha || 0.0 );
  583. renderer.clear();
  584. }
  585. this.scene.traverseVisible( child => {
  586. child._SSRPassBackupMaterial = child.material;
  587. if ( this._selects.includes( child ) ) {
  588. child.material = this.metalnessOnMaterial;
  589. } else {
  590. child.material = this.metalnessOffMaterial;
  591. }
  592. } );
  593. renderer.render( this.scene, this.camera );
  594. this.scene.traverseVisible( child => {
  595. child.material = child._SSRPassBackupMaterial;
  596. } );
  597. // restore original state
  598. renderer.autoClear = originalAutoClear;
  599. renderer.setClearColor( this.originalClearColor );
  600. renderer.setClearAlpha( originalClearAlpha );
  601. this.scene.background = originalBackground;
  602. this.scene.fog = originalFog;
  603. }
  604. }
  605. /**
  606. * Constructor options of `SSRPass`.
  607. *
  608. * @typedef {Object} SSRPass~Options
  609. * @property {WebGLRenderer} renderer - The renderer.
  610. * @property {Scene} scene - The scene to render.
  611. * @property {Camera} camera - The camera.
  612. * @property {number} [width=512] - The width of the effect.
  613. * @property {number} [height=512] - The width of the effect.
  614. * @property {?Array<Object3D>} [selects=null] - Which 3D objects should be affected by SSR. If not set, the entire scene is affected.
  615. * @property {boolean} [bouncing=false] - Whether bouncing is enabled or not.
  616. * @property {?ReflectorForSSRPass} [groundReflector=null] - A ground reflector.
  617. **/
  618. SSRPass.OUTPUT = {
  619. 'Default': 0,
  620. 'SSR': 1,
  621. 'Beauty': 3,
  622. 'Depth': 4,
  623. 'Normal': 5,
  624. 'Metalness': 7,
  625. };
  626. export { SSRPass };