SSRPass.js 23 KB

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