WebGPUBackground.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. uvNode: transformDirection( positionWorld, modelWorldMatrix )
  49. } );
  50. }
  51. const nodeMaterial = new MeshBasicNodeMaterial();
  52. nodeMaterial.colorNode = node;
  53. nodeMaterial.side = BackSide;
  54. nodeMaterial.depthTest = false;
  55. nodeMaterial.depthWrite = false;
  56. nodeMaterial.fog = false;
  57. this.boxMesh = boxMesh = new Mesh( new BoxGeometry( 1, 1, 1 ), nodeMaterial );
  58. boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
  59. this.matrixWorld.copyPosition( camera.matrixWorld );
  60. };
  61. }
  62. renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
  63. } else {
  64. console.error( 'THREE.WebGPURenderer: Unsupported background configuration.', background );
  65. }
  66. // configure render pass descriptor
  67. const renderPassDescriptor = renderer._renderPassDescriptor;
  68. const colorAttachment = renderPassDescriptor.colorAttachments[ 0 ];
  69. const depthStencilAttachment = renderPassDescriptor.depthStencilAttachment;
  70. if ( renderer.autoClear === true || forceClear === true ) {
  71. if ( renderer.autoClearColor === true ) {
  72. _clearColor.multiplyScalar( _clearAlpha );
  73. colorAttachment.clearValue = { r: _clearColor.r, g: _clearColor.g, b: _clearColor.b, a: _clearAlpha };
  74. colorAttachment.loadOp = GPULoadOp.Clear;
  75. colorAttachment.storeOp = GPUStoreOp.Store;
  76. } else {
  77. colorAttachment.loadOp = GPULoadOp.Load;
  78. }
  79. if ( renderer.autoClearDepth === true ) {
  80. depthStencilAttachment.depthClearValue = renderer._clearDepth;
  81. depthStencilAttachment.depthLoadOp = GPULoadOp.Clear;
  82. } else {
  83. depthStencilAttachment.depthLoadOp = GPULoadOp.Load;
  84. }
  85. if ( renderer.autoClearStencil === true ) {
  86. depthStencilAttachment.stencilClearValue = renderer._clearStencil;
  87. depthStencilAttachment.stencilLoadOp = GPULoadOp.Clear;
  88. } else {
  89. depthStencilAttachment.stencilLoadOp = GPULoadOp.Load;
  90. }
  91. } else {
  92. colorAttachment.loadOp = GPULoadOp.Load;
  93. depthStencilAttachment.depthLoadOp = GPULoadOp.Load;
  94. depthStencilAttachment.stencilLoadOp = GPULoadOp.Load;
  95. }
  96. this.forceClear = false;
  97. }
  98. }
  99. export default WebGPUBackground;