WebGLBackground.js 5.2 KB

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