WebGLBackground.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import { BackSide, FrontSide, CubeUVReflectionMapping, SRGBTransfer } from '../../constants.js';
  2. import { BoxGeometry } from '../../geometries/BoxGeometry.js';
  3. import { PlaneGeometry } from '../../geometries/PlaneGeometry.js';
  4. import { ShaderMaterial } from '../../materials/ShaderMaterial.js';
  5. import { Color } from '../../math/Color.js';
  6. import { ColorManagement } from '../../math/ColorManagement.js';
  7. import { Euler } from '../../math/Euler.js';
  8. import { Matrix4 } from '../../math/Matrix4.js';
  9. import { Mesh } from '../../objects/Mesh.js';
  10. import { ShaderLib } from '../shaders/ShaderLib.js';
  11. import { cloneUniforms, getUnlitUniformColorSpace } from '../shaders/UniformsUtils.js';
  12. const _rgb = { r: 0, b: 0, g: 0 };
  13. const _e1 = /*@__PURE__*/ new Euler();
  14. const _m1 = /*@__PURE__*/ new Matrix4();
  15. function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, premultipliedAlpha ) {
  16. const clearColor = new Color( 0x000000 );
  17. let clearAlpha = alpha === true ? 0 : 1;
  18. let planeMesh;
  19. let boxMesh;
  20. let currentBackground = null;
  21. let currentBackgroundVersion = 0;
  22. let currentTonemapping = null;
  23. function render( renderList, scene ) {
  24. let forceClear = false;
  25. let background = scene.isScene === true ? scene.background : null;
  26. if ( background && background.isTexture ) {
  27. const usePMREM = scene.backgroundBlurriness > 0; // use PMREM if the user wants to blur the background
  28. background = ( usePMREM ? cubeuvmaps : cubemaps ).get( background );
  29. }
  30. if ( background === null ) {
  31. setClear( clearColor, clearAlpha );
  32. } else if ( background && background.isColor ) {
  33. setClear( background, 1 );
  34. forceClear = true;
  35. }
  36. const environmentBlendMode = renderer.xr.getEnvironmentBlendMode();
  37. if ( environmentBlendMode === 'additive' ) {
  38. state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha );
  39. } else if ( environmentBlendMode === 'alpha-blend' ) {
  40. state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha );
  41. }
  42. if ( renderer.autoClear || forceClear ) {
  43. renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
  44. }
  45. if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) {
  46. if ( boxMesh === undefined ) {
  47. boxMesh = new Mesh(
  48. new BoxGeometry( 1, 1, 1 ),
  49. new ShaderMaterial( {
  50. name: 'BackgroundCubeMaterial',
  51. uniforms: cloneUniforms( ShaderLib.backgroundCube.uniforms ),
  52. vertexShader: ShaderLib.backgroundCube.vertexShader,
  53. fragmentShader: ShaderLib.backgroundCube.fragmentShader,
  54. side: BackSide,
  55. depthTest: false,
  56. depthWrite: false,
  57. fog: false
  58. } )
  59. );
  60. boxMesh.geometry.deleteAttribute( 'normal' );
  61. boxMesh.geometry.deleteAttribute( 'uv' );
  62. boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
  63. this.matrixWorld.copyPosition( camera.matrixWorld );
  64. };
  65. // add "envMap" material property so the renderer can evaluate it like for built-in materials
  66. Object.defineProperty( boxMesh.material, 'envMap', {
  67. get: function () {
  68. return this.uniforms.envMap.value;
  69. }
  70. } );
  71. objects.update( boxMesh );
  72. }
  73. _e1.copy( scene.backgroundRotation );
  74. // accommodate left-handed frame
  75. _e1.x *= - 1; _e1.y *= - 1; _e1.z *= - 1;
  76. if ( background.isCubeTexture && background.isRenderTargetTexture === false ) {
  77. // environment maps which are not cube render targets or PMREMs follow a different convention
  78. _e1.y *= - 1;
  79. _e1.z *= - 1;
  80. }
  81. boxMesh.material.uniforms.envMap.value = background;
  82. boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1;
  83. boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness;
  84. boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
  85. boxMesh.material.uniforms.backgroundRotation.value.setFromMatrix4( _m1.makeRotationFromEuler( _e1 ) );
  86. boxMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer;
  87. if ( currentBackground !== background ||
  88. currentBackgroundVersion !== background.version ||
  89. currentTonemapping !== renderer.toneMapping ) {
  90. boxMesh.material.needsUpdate = true;
  91. currentBackground = background;
  92. currentBackgroundVersion = background.version;
  93. currentTonemapping = renderer.toneMapping;
  94. }
  95. boxMesh.layers.enableAll();
  96. // push to the pre-sorted opaque render list
  97. renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
  98. } else if ( background && background.isTexture ) {
  99. if ( planeMesh === undefined ) {
  100. planeMesh = new Mesh(
  101. new PlaneGeometry( 2, 2 ),
  102. new ShaderMaterial( {
  103. name: 'BackgroundMaterial',
  104. uniforms: cloneUniforms( ShaderLib.background.uniforms ),
  105. vertexShader: ShaderLib.background.vertexShader,
  106. fragmentShader: ShaderLib.background.fragmentShader,
  107. side: FrontSide,
  108. depthTest: false,
  109. depthWrite: false,
  110. fog: false
  111. } )
  112. );
  113. planeMesh.geometry.deleteAttribute( 'normal' );
  114. // add "map" material property so the renderer can evaluate it like for built-in materials
  115. Object.defineProperty( planeMesh.material, 'map', {
  116. get: function () {
  117. return this.uniforms.t2D.value;
  118. }
  119. } );
  120. objects.update( planeMesh );
  121. }
  122. planeMesh.material.uniforms.t2D.value = background;
  123. planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
  124. planeMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer;
  125. if ( background.matrixAutoUpdate === true ) {
  126. background.updateMatrix();
  127. }
  128. planeMesh.material.uniforms.uvTransform.value.copy( background.matrix );
  129. if ( currentBackground !== background ||
  130. currentBackgroundVersion !== background.version ||
  131. currentTonemapping !== renderer.toneMapping ) {
  132. planeMesh.material.needsUpdate = true;
  133. currentBackground = background;
  134. currentBackgroundVersion = background.version;
  135. currentTonemapping = renderer.toneMapping;
  136. }
  137. planeMesh.layers.enableAll();
  138. // push to the pre-sorted opaque render list
  139. renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );
  140. }
  141. }
  142. function setClear( color, alpha ) {
  143. color.getRGB( _rgb, getUnlitUniformColorSpace( renderer ) );
  144. state.buffers.color.setClear( _rgb.r, _rgb.g, _rgb.b, alpha, premultipliedAlpha );
  145. }
  146. return {
  147. getClearColor: function () {
  148. return clearColor;
  149. },
  150. setClearColor: function ( color, alpha = 1 ) {
  151. clearColor.set( color );
  152. clearAlpha = alpha;
  153. setClear( clearColor, clearAlpha );
  154. },
  155. getClearAlpha: function () {
  156. return clearAlpha;
  157. },
  158. setClearAlpha: function ( alpha ) {
  159. clearAlpha = alpha;
  160. setClear( clearColor, clearAlpha );
  161. },
  162. render: render
  163. };
  164. }
  165. export { WebGLBackground };
粤ICP备19079148号