WebGPUBackground.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import { GPULoadOp, GPUStoreOp } from './constants.js';
  2. import { Color, Mesh, BoxGeometry, BackSide, EquirectangularReflectionMapping, EquirectangularRefractionMapping } from 'three';
  3. import { context, vec2, invert, texture, cubeTexture, transformDirection, positionWorld, modelWorldMatrix, viewportBottomLeft, equirectUV, MeshBasicNodeMaterial } from 'three/nodes';
  4. let _clearAlpha;
  5. const _clearColor = new Color();
  6. class WebGPUBackground {
  7. constructor( renderer ) {
  8. this.renderer = renderer;
  9. this.boxMesh = null;
  10. this.forceClear = false;
  11. }
  12. clear() {
  13. this.forceClear = true;
  14. }
  15. update( renderList, scene ) {
  16. const renderer = this.renderer;
  17. const background = ( scene.isScene === true ) ? scene.backgroundNode || scene.background : null;
  18. let forceClear = this.forceClear;
  19. if ( background === null ) {
  20. // no background settings, use clear color configuration from the renderer
  21. _clearColor.copy( renderer._clearColor );
  22. _clearAlpha = renderer._clearAlpha;
  23. } else if ( background.isColor === true ) {
  24. // background is an opaque color
  25. _clearColor.copy( background );
  26. _clearAlpha = 1;
  27. forceClear = true;
  28. } else if ( background.isNode === true || background.isTexture === true ) {
  29. _clearColor.copy( renderer._clearColor );
  30. _clearAlpha = renderer._clearAlpha;
  31. let boxMesh = this.boxMesh;
  32. if ( boxMesh === null ) {
  33. let node = null;
  34. if ( background.isCubeTexture === true ) {
  35. node = cubeTexture( background, transformDirection( positionWorld, modelWorldMatrix ) );
  36. } else if ( background.isTexture === true ) {
  37. let nodeUV = null;
  38. if ( background.mapping === EquirectangularReflectionMapping || background.mapping === EquirectangularRefractionMapping ) {
  39. const dirNode = transformDirection( positionWorld, modelWorldMatrix );
  40. nodeUV = equirectUV( dirNode );
  41. nodeUV = vec2( nodeUV.x, invert( nodeUV.y ) );
  42. } else {
  43. nodeUV = viewportBottomLeft;
  44. }
  45. node = texture( background, nodeUV );
  46. } else /*if ( background.isNode === true )*/ {
  47. node = context( background, {
  48. // @TODO: Add Texture2D support using node context
  49. getUVNode: () => transformDirection( positionWorld, modelWorldMatrix )
  50. } );
  51. }
  52. const nodeMaterial = new MeshBasicNodeMaterial();
  53. nodeMaterial.colorNode = node;
  54. nodeMaterial.side = BackSide;
  55. nodeMaterial.depthTest = false;
  56. nodeMaterial.depthWrite = false;
  57. nodeMaterial.fog = false;
  58. this.boxMesh = boxMesh = new Mesh( new BoxGeometry( 1, 1, 1 ), nodeMaterial );
  59. boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
  60. this.matrixWorld.copyPosition( camera.matrixWorld );
  61. };
  62. }
  63. renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
  64. } else {
  65. console.error( 'THREE.WebGPURenderer: Unsupported background configuration.', background );
  66. }
  67. // configure render pass descriptor
  68. const renderPassDescriptor = renderer._renderPassDescriptor;
  69. const colorAttachment = renderPassDescriptor.colorAttachments[ 0 ];
  70. const depthStencilAttachment = renderPassDescriptor.depthStencilAttachment;
  71. if ( renderer.autoClear === true || forceClear === true ) {
  72. if ( renderer.autoClearColor === true ) {
  73. _clearColor.multiplyScalar( _clearAlpha );
  74. colorAttachment.clearValue = { r: _clearColor.r, g: _clearColor.g, b: _clearColor.b, a: _clearAlpha };
  75. colorAttachment.loadOp = GPULoadOp.Clear;
  76. colorAttachment.storeOp = GPUStoreOp.Store;
  77. } else {
  78. colorAttachment.loadOp = GPULoadOp.Load;
  79. colorAttachment.storeOp = GPUStoreOp.Store;
  80. }
  81. if ( renderer.autoClearDepth === true ) {
  82. depthStencilAttachment.depthClearValue = renderer._clearDepth;
  83. depthStencilAttachment.depthLoadOp = GPULoadOp.Clear;
  84. depthStencilAttachment.depthStoreOp = GPUStoreOp.Store;
  85. } else {
  86. depthStencilAttachment.depthLoadOp = GPULoadOp.Load;
  87. depthStencilAttachment.depthStoreOp = GPUStoreOp.Store;
  88. }
  89. if ( renderer.autoClearStencil === true ) {
  90. depthStencilAttachment.stencilClearValue = renderer._clearStencil;
  91. depthStencilAttachment.stencilLoadOp = GPULoadOp.Clear;
  92. depthStencilAttachment.stencilStoreOp = GPUStoreOp.Store;
  93. } else {
  94. depthStencilAttachment.stencilLoadOp = GPULoadOp.Load;
  95. depthStencilAttachment.stencilStoreOp = GPUStoreOp.Store;
  96. }
  97. } else {
  98. colorAttachment.loadOp = GPULoadOp.Load;
  99. depthStencilAttachment.depthLoadOp = GPULoadOp.Load;
  100. depthStencilAttachment.stencilLoadOp = GPULoadOp.Load;
  101. }
  102. this.forceClear = false;
  103. }
  104. }
  105. export default WebGPUBackground;