1
0

SSRPass.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858
  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. this._resolutionScale = 1;
  124. /**
  125. * Whether the pass is selective or not.
  126. *
  127. * @type {boolean}
  128. * @default false
  129. */
  130. this.selective = Array.isArray( this._selects );
  131. /**
  132. * Which 3D objects should be affected by SSR. If not set, the entire scene is affected.
  133. *
  134. * @name SSRPass#selects
  135. * @type {?Array<Object3D>}
  136. * @default null
  137. */
  138. Object.defineProperty( this, 'selects', {
  139. get() {
  140. return this._selects;
  141. },
  142. set( val ) {
  143. if ( this._selects === val ) return;
  144. this._selects = val;
  145. if ( Array.isArray( val ) ) {
  146. this.selective = true;
  147. this.ssrMaterial.defines.SELECTIVE = true;
  148. this.ssrMaterial.needsUpdate = true;
  149. } else {
  150. this.selective = false;
  151. this.ssrMaterial.defines.SELECTIVE = false;
  152. this.ssrMaterial.needsUpdate = true;
  153. }
  154. }
  155. } );
  156. this._bouncing = bouncing;
  157. /**
  158. * Whether bouncing is enabled or not.
  159. *
  160. * @name SSRPass#bouncing
  161. * @type {boolean}
  162. * @default false
  163. */
  164. Object.defineProperty( this, 'bouncing', {
  165. get() {
  166. return this._bouncing;
  167. },
  168. set( val ) {
  169. if ( this._bouncing === val ) return;
  170. this._bouncing = val;
  171. if ( val ) {
  172. this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.prevRenderTarget.texture;
  173. } else {
  174. this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
  175. }
  176. }
  177. } );
  178. /**
  179. * Whether to blur reflections or not.
  180. *
  181. * @type {boolean}
  182. * @default true
  183. */
  184. this.blur = true;
  185. this._distanceAttenuation = SSRShader.defines.DISTANCE_ATTENUATION;
  186. /**
  187. * Whether to use distance attenuation or not.
  188. *
  189. * @name SSRPass#distanceAttenuation
  190. * @type {boolean}
  191. * @default true
  192. */
  193. Object.defineProperty( this, 'distanceAttenuation', {
  194. get() {
  195. return this._distanceAttenuation;
  196. },
  197. set( val ) {
  198. if ( this._distanceAttenuation === val ) return;
  199. this._distanceAttenuation = val;
  200. this.ssrMaterial.defines.DISTANCE_ATTENUATION = val;
  201. this.ssrMaterial.needsUpdate = true;
  202. }
  203. } );
  204. this._fresnel = SSRShader.defines.FRESNEL;
  205. /**
  206. * Whether to use fresnel or not.
  207. *
  208. * @name SSRPass#fresnel
  209. * @type {boolean}
  210. * @default true
  211. */
  212. Object.defineProperty( this, 'fresnel', {
  213. get() {
  214. return this._fresnel;
  215. },
  216. set( val ) {
  217. if ( this._fresnel === val ) return;
  218. this._fresnel = val;
  219. this.ssrMaterial.defines.FRESNEL = val;
  220. this.ssrMaterial.needsUpdate = true;
  221. }
  222. } );
  223. this._infiniteThick = SSRShader.defines.INFINITE_THICK;
  224. /**
  225. * Whether to use infinite thickness or not.
  226. *
  227. * @name SSRPass#infiniteThick
  228. * @type {boolean}
  229. * @default false
  230. */
  231. Object.defineProperty( this, 'infiniteThick', {
  232. get() {
  233. return this._infiniteThick;
  234. },
  235. set( val ) {
  236. if ( this._infiniteThick === val ) return;
  237. this._infiniteThick = val;
  238. this.ssrMaterial.defines.INFINITE_THICK = val;
  239. this.ssrMaterial.needsUpdate = true;
  240. }
  241. } );
  242. // beauty render target with depth buffer
  243. const depthTexture = new DepthTexture();
  244. depthTexture.type = UnsignedShortType;
  245. depthTexture.minFilter = NearestFilter;
  246. depthTexture.magFilter = NearestFilter;
  247. this.beautyRenderTarget = new WebGLRenderTarget( this.width, this.height, {
  248. minFilter: NearestFilter,
  249. magFilter: NearestFilter,
  250. type: HalfFloatType,
  251. depthTexture: depthTexture,
  252. depthBuffer: true
  253. } );
  254. //for bouncing
  255. this.prevRenderTarget = new WebGLRenderTarget( this.width, this.height, {
  256. minFilter: NearestFilter,
  257. magFilter: NearestFilter,
  258. depthBuffer: false
  259. } );
  260. // normal render target
  261. this.normalRenderTarget = new WebGLRenderTarget( this.width, this.height, {
  262. minFilter: NearestFilter,
  263. magFilter: NearestFilter,
  264. type: HalfFloatType,
  265. } );
  266. // metalness render target
  267. this.metalnessRenderTarget = new WebGLRenderTarget( this.width, this.height, {
  268. minFilter: NearestFilter,
  269. magFilter: NearestFilter,
  270. type: HalfFloatType,
  271. } );
  272. // ssr render target
  273. this.ssrRenderTarget = new WebGLRenderTarget( this.width, this.height, {
  274. minFilter: NearestFilter,
  275. magFilter: NearestFilter,
  276. depthBuffer: false
  277. } );
  278. this.blurRenderTarget = this.ssrRenderTarget.clone();
  279. this.blurRenderTarget2 = this.ssrRenderTarget.clone();
  280. // this.blurRenderTarget3 = this.ssrRenderTarget.clone();
  281. // ssr material
  282. this.ssrMaterial = new ShaderMaterial( {
  283. defines: Object.assign( {}, SSRShader.defines, {
  284. MAX_STEP: Math.sqrt( this.width * this.width + this.height * this.height )
  285. } ),
  286. uniforms: UniformsUtils.clone( SSRShader.uniforms ),
  287. vertexShader: SSRShader.vertexShader,
  288. fragmentShader: SSRShader.fragmentShader,
  289. blending: NoBlending
  290. } );
  291. this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
  292. this.ssrMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture;
  293. this.ssrMaterial.defines.SELECTIVE = this.selective;
  294. this.ssrMaterial.needsUpdate = true;
  295. this.ssrMaterial.uniforms[ 'tMetalness' ].value = this.metalnessRenderTarget.texture;
  296. this.ssrMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture;
  297. this.ssrMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
  298. this.ssrMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
  299. this.ssrMaterial.uniforms[ 'thickness' ].value = this.thickness;
  300. this.ssrMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );
  301. this.ssrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
  302. this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
  303. // normal material
  304. this.normalMaterial = new MeshNormalMaterial();
  305. this.normalMaterial.blending = NoBlending;
  306. // metalnessOn material
  307. this.metalnessOnMaterial = new MeshBasicMaterial( {
  308. color: 'white'
  309. } );
  310. // metalnessOff material
  311. this.metalnessOffMaterial = new MeshBasicMaterial( {
  312. color: 'black'
  313. } );
  314. // blur material
  315. this.blurMaterial = new ShaderMaterial( {
  316. defines: Object.assign( {}, SSRBlurShader.defines ),
  317. uniforms: UniformsUtils.clone( SSRBlurShader.uniforms ),
  318. vertexShader: SSRBlurShader.vertexShader,
  319. fragmentShader: SSRBlurShader.fragmentShader
  320. } );
  321. this.blurMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
  322. this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );
  323. // blur material 2
  324. this.blurMaterial2 = new ShaderMaterial( {
  325. defines: Object.assign( {}, SSRBlurShader.defines ),
  326. uniforms: UniformsUtils.clone( SSRBlurShader.uniforms ),
  327. vertexShader: SSRBlurShader.vertexShader,
  328. fragmentShader: SSRBlurShader.fragmentShader
  329. } );
  330. this.blurMaterial2.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture;
  331. this.blurMaterial2.uniforms[ 'resolution' ].value.set( this.width, this.height );
  332. // // blur material 3
  333. // this.blurMaterial3 = new ShaderMaterial({
  334. // defines: Object.assign({}, SSRBlurShader.defines),
  335. // uniforms: UniformsUtils.clone(SSRBlurShader.uniforms),
  336. // vertexShader: SSRBlurShader.vertexShader,
  337. // fragmentShader: SSRBlurShader.fragmentShader
  338. // });
  339. // this.blurMaterial3.uniforms['tDiffuse'].value = this.blurRenderTarget2.texture;
  340. // this.blurMaterial3.uniforms['resolution'].value.set(this.width, this.height);
  341. // material for rendering the depth
  342. this.depthRenderMaterial = new ShaderMaterial( {
  343. defines: Object.assign( {}, SSRDepthShader.defines ),
  344. uniforms: UniformsUtils.clone( SSRDepthShader.uniforms ),
  345. vertexShader: SSRDepthShader.vertexShader,
  346. fragmentShader: SSRDepthShader.fragmentShader,
  347. blending: NoBlending
  348. } );
  349. this.depthRenderMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture;
  350. this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
  351. this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
  352. // material for rendering the content of a render target
  353. this.copyMaterial = new ShaderMaterial( {
  354. uniforms: UniformsUtils.clone( CopyShader.uniforms ),
  355. vertexShader: CopyShader.vertexShader,
  356. fragmentShader: CopyShader.fragmentShader,
  357. transparent: true,
  358. depthTest: false,
  359. depthWrite: false,
  360. blendSrc: SrcAlphaFactor,
  361. blendDst: OneMinusSrcAlphaFactor,
  362. blendEquation: AddEquation,
  363. blendSrcAlpha: SrcAlphaFactor,
  364. blendDstAlpha: OneMinusSrcAlphaFactor,
  365. blendEquationAlpha: AddEquation,
  366. // premultipliedAlpha:true,
  367. } );
  368. this.fsQuad = new FullScreenQuad( null );
  369. this.originalClearColor = new Color();
  370. }
  371. /**
  372. * The resolution scale. Valid values are in the range
  373. * `[0,1]`. `1` means best quality but also results in
  374. * more computational overhead. Setting to `0.5` means
  375. * the effect is computed in half-resolution.
  376. *
  377. * @type {number}
  378. * @default 1
  379. */
  380. get resolutionScale() {
  381. return this._resolutionScale;
  382. }
  383. set resolutionScale( value ) {
  384. this._resolutionScale = value;
  385. this.setSize( this.width, this.height ); // force a resize when resolution scaling changes
  386. }
  387. /**
  388. * Frees the GPU-related resources allocated by this instance. Call this
  389. * method whenever the pass is no longer used in your app.
  390. */
  391. dispose() {
  392. // dispose render targets
  393. this.beautyRenderTarget.dispose();
  394. this.prevRenderTarget.dispose();
  395. this.normalRenderTarget.dispose();
  396. this.metalnessRenderTarget.dispose();
  397. this.ssrRenderTarget.dispose();
  398. this.blurRenderTarget.dispose();
  399. this.blurRenderTarget2.dispose();
  400. // this.blurRenderTarget3.dispose();
  401. // dispose materials
  402. this.normalMaterial.dispose();
  403. this.metalnessOnMaterial.dispose();
  404. this.metalnessOffMaterial.dispose();
  405. this.blurMaterial.dispose();
  406. this.blurMaterial2.dispose();
  407. this.copyMaterial.dispose();
  408. this.depthRenderMaterial.dispose();
  409. // dispose full screen quad
  410. this.fsQuad.dispose();
  411. }
  412. /**
  413. * Performs the SSR pass.
  414. *
  415. * @param {WebGLRenderer} renderer - The renderer.
  416. * @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
  417. * destination for the pass.
  418. * @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
  419. * previous pass from this buffer.
  420. * @param {number} deltaTime - The delta time in seconds.
  421. * @param {boolean} maskActive - Whether masking is active or not.
  422. */
  423. render( renderer, writeBuffer /*, readBuffer, deltaTime, maskActive */ ) {
  424. // render beauty and depth
  425. renderer.setRenderTarget( this.beautyRenderTarget );
  426. renderer.clear();
  427. if ( this.groundReflector ) {
  428. this.groundReflector.visible = false;
  429. this.groundReflector.doRender( this.renderer, this.scene, this.camera );
  430. this.groundReflector.visible = true;
  431. }
  432. renderer.render( this.scene, this.camera );
  433. if ( this.groundReflector ) this.groundReflector.visible = false;
  434. // render normals
  435. this._renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0, 0 );
  436. // render metalnesses
  437. if ( this.selective ) {
  438. this._renderMetalness( renderer, this.metalnessOnMaterial, this.metalnessRenderTarget, 0, 0 );
  439. }
  440. // render SSR
  441. this.ssrMaterial.uniforms[ 'opacity' ].value = this.opacity;
  442. this.ssrMaterial.uniforms[ 'maxDistance' ].value = this.maxDistance;
  443. this.ssrMaterial.uniforms[ 'thickness' ].value = this.thickness;
  444. this._renderPass( renderer, this.ssrMaterial, this.ssrRenderTarget );
  445. // render blur
  446. if ( this.blur ) {
  447. this._renderPass( renderer, this.blurMaterial, this.blurRenderTarget );
  448. this._renderPass( renderer, this.blurMaterial2, this.blurRenderTarget2 );
  449. // this._renderPass(renderer, this.blurMaterial3, this.blurRenderTarget3);
  450. }
  451. // output result to screen
  452. switch ( this.output ) {
  453. case SSRPass.OUTPUT.Default:
  454. if ( this.bouncing ) {
  455. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
  456. this.copyMaterial.blending = NoBlending;
  457. this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
  458. if ( this.blur )
  459. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture;
  460. else
  461. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
  462. this.copyMaterial.blending = NormalBlending;
  463. this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
  464. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.prevRenderTarget.texture;
  465. this.copyMaterial.blending = NoBlending;
  466. this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
  467. } else {
  468. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
  469. this.copyMaterial.blending = NoBlending;
  470. this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
  471. if ( this.blur )
  472. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture;
  473. else
  474. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
  475. this.copyMaterial.blending = NormalBlending;
  476. this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
  477. }
  478. break;
  479. case SSRPass.OUTPUT.SSR:
  480. if ( this.blur )
  481. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture;
  482. else
  483. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
  484. this.copyMaterial.blending = NoBlending;
  485. this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
  486. if ( this.bouncing ) {
  487. if ( this.blur )
  488. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture;
  489. else
  490. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
  491. this.copyMaterial.blending = NoBlending;
  492. this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
  493. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
  494. this.copyMaterial.blending = NormalBlending;
  495. this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
  496. }
  497. break;
  498. case SSRPass.OUTPUT.Beauty:
  499. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
  500. this.copyMaterial.blending = NoBlending;
  501. this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
  502. break;
  503. case SSRPass.OUTPUT.Depth:
  504. this._renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : writeBuffer );
  505. break;
  506. case SSRPass.OUTPUT.Normal:
  507. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.normalRenderTarget.texture;
  508. this.copyMaterial.blending = NoBlending;
  509. this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
  510. break;
  511. case SSRPass.OUTPUT.Metalness:
  512. this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.metalnessRenderTarget.texture;
  513. this.copyMaterial.blending = NoBlending;
  514. this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
  515. break;
  516. default:
  517. console.warn( 'THREE.SSRPass: Unknown output type.' );
  518. }
  519. }
  520. /**
  521. * Sets the size of the pass.
  522. *
  523. * @param {number} width - The width to set.
  524. * @param {number} height - The height to set.
  525. */
  526. setSize( width, height ) {
  527. this.width = width;
  528. this.height = height;
  529. const effectiveWidth = Math.round( this.resolutionScale * width );
  530. const effectiveHeight = Math.round( this.resolutionScale * height );
  531. this.ssrMaterial.defines.MAX_STEP = Math.sqrt( effectiveWidth * effectiveWidth + effectiveHeight * effectiveHeight );
  532. this.ssrMaterial.needsUpdate = true;
  533. this.beautyRenderTarget.setSize( width, height );
  534. this.normalRenderTarget.setSize( width, height );
  535. this.metalnessRenderTarget.setSize( width, height );
  536. this.ssrRenderTarget.setSize( effectiveWidth, effectiveHeight );
  537. this.prevRenderTarget.setSize( effectiveWidth, effectiveHeight );
  538. this.blurRenderTarget.setSize( effectiveWidth, effectiveHeight );
  539. this.blurRenderTarget2.setSize( effectiveWidth, effectiveHeight );
  540. // this.blurRenderTarget3.setSize(width, height);
  541. this.ssrMaterial.uniforms[ 'resolution' ].value.set( effectiveWidth, effectiveHeight );
  542. this.ssrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
  543. this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
  544. this.blurMaterial.uniforms[ 'resolution' ].value.set( effectiveWidth, effectiveHeight );
  545. this.blurMaterial2.uniforms[ 'resolution' ].value.set( effectiveWidth, effectiveHeight );
  546. }
  547. // internals
  548. _renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
  549. // save original state
  550. this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) );
  551. const originalClearAlpha = renderer.getClearAlpha( this.tempColor );
  552. const originalAutoClear = renderer.autoClear;
  553. renderer.setRenderTarget( renderTarget );
  554. // setup pass state
  555. renderer.autoClear = false;
  556. if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
  557. renderer.setClearColor( clearColor );
  558. renderer.setClearAlpha( clearAlpha || 0.0 );
  559. renderer.clear();
  560. }
  561. this.fsQuad.material = passMaterial;
  562. this.fsQuad.render( renderer );
  563. // restore original state
  564. renderer.autoClear = originalAutoClear;
  565. renderer.setClearColor( this.originalClearColor );
  566. renderer.setClearAlpha( originalClearAlpha );
  567. }
  568. _renderOverride( 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. renderer.setRenderTarget( renderTarget );
  573. renderer.autoClear = false;
  574. clearColor = overrideMaterial.clearColor || clearColor;
  575. clearAlpha = overrideMaterial.clearAlpha || clearAlpha;
  576. if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
  577. renderer.setClearColor( clearColor );
  578. renderer.setClearAlpha( clearAlpha || 0.0 );
  579. renderer.clear();
  580. }
  581. this.scene.overrideMaterial = overrideMaterial;
  582. renderer.render( this.scene, this.camera );
  583. this.scene.overrideMaterial = null;
  584. // restore original state
  585. renderer.autoClear = originalAutoClear;
  586. renderer.setClearColor( this.originalClearColor );
  587. renderer.setClearAlpha( originalClearAlpha );
  588. }
  589. _renderMetalness( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
  590. this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) );
  591. const originalClearAlpha = renderer.getClearAlpha( this.tempColor );
  592. const originalAutoClear = renderer.autoClear;
  593. const originalBackground = this.scene.background;
  594. const originalFog = this.scene.fog;
  595. renderer.setRenderTarget( renderTarget );
  596. renderer.autoClear = false;
  597. this.scene.background = null;
  598. this.scene.fog = null;
  599. clearColor = overrideMaterial.clearColor || clearColor;
  600. clearAlpha = overrideMaterial.clearAlpha || clearAlpha;
  601. if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
  602. renderer.setClearColor( clearColor );
  603. renderer.setClearAlpha( clearAlpha || 0.0 );
  604. renderer.clear();
  605. }
  606. this.scene.traverseVisible( child => {
  607. child._SSRPassBackupMaterial = child.material;
  608. if ( this._selects.includes( child ) ) {
  609. child.material = this.metalnessOnMaterial;
  610. } else {
  611. child.material = this.metalnessOffMaterial;
  612. }
  613. } );
  614. renderer.render( this.scene, this.camera );
  615. this.scene.traverseVisible( child => {
  616. child.material = child._SSRPassBackupMaterial;
  617. } );
  618. // restore original state
  619. renderer.autoClear = originalAutoClear;
  620. renderer.setClearColor( this.originalClearColor );
  621. renderer.setClearAlpha( originalClearAlpha );
  622. this.scene.background = originalBackground;
  623. this.scene.fog = originalFog;
  624. }
  625. }
  626. /**
  627. * Constructor options of `SSRPass`.
  628. *
  629. * @typedef {Object} SSRPass~Options
  630. * @property {WebGLRenderer} renderer - The renderer.
  631. * @property {Scene} scene - The scene to render.
  632. * @property {Camera} camera - The camera.
  633. * @property {number} [width=512] - The width of the effect.
  634. * @property {number} [height=512] - The width of the effect.
  635. * @property {?Array<Object3D>} [selects=null] - Which 3D objects should be affected by SSR. If not set, the entire scene is affected.
  636. * @property {boolean} [bouncing=false] - Whether bouncing is enabled or not.
  637. * @property {?ReflectorForSSRPass} [groundReflector=null] - A ground reflector.
  638. **/
  639. SSRPass.OUTPUT = {
  640. 'Default': 0,
  641. 'SSR': 1,
  642. 'Beauty': 3,
  643. 'Depth': 4,
  644. 'Normal': 5,
  645. 'Metalness': 7,
  646. };
  647. export { SSRPass };
粤ICP备19079148号