WebGLBackground.js 6.2 KB

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