WebGPUBackground.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import { GPULoadOp, GPUStoreOp } from './constants.js';
  2. import { Color, Mesh, BoxGeometry, BackSide } from 'three';
  3. import { context, transformDirection, positionWorld, modelWorldMatrix, 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 ) {
  29. _clearColor.copy( renderer._clearColor );
  30. _clearAlpha = renderer._clearAlpha;
  31. let boxMesh = this.boxMesh;
  32. if ( boxMesh === null ) {
  33. const colorNode = context( background, {
  34. uvNode: transformDirection( positionWorld, modelWorldMatrix )
  35. } );
  36. const nodeMaterial = new MeshBasicNodeMaterial();
  37. nodeMaterial.colorNode = colorNode;
  38. nodeMaterial.side = BackSide;
  39. nodeMaterial.depthTest = false;
  40. nodeMaterial.depthWrite = false;
  41. nodeMaterial.fog = false;
  42. this.boxMesh = boxMesh = new Mesh( new BoxGeometry( 1, 1, 1 ), nodeMaterial );
  43. boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
  44. this.matrixWorld.copyPosition( camera.matrixWorld );
  45. };
  46. }
  47. renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
  48. } else {
  49. console.error( 'THREE.WebGPURenderer: Unsupported background configuration.', background );
  50. }
  51. // configure render pass descriptor
  52. const renderPassDescriptor = renderer._renderPassDescriptor;
  53. const colorAttachment = renderPassDescriptor.colorAttachments[ 0 ];
  54. const depthStencilAttachment = renderPassDescriptor.depthStencilAttachment;
  55. if ( renderer.autoClear === true || forceClear === true ) {
  56. if ( renderer.autoClearColor === true ) {
  57. _clearColor.multiplyScalar( _clearAlpha );
  58. colorAttachment.clearValue = { r: _clearColor.r, g: _clearColor.g, b: _clearColor.b, a: _clearAlpha };
  59. colorAttachment.loadOp = GPULoadOp.Clear;
  60. colorAttachment.storeOp = GPUStoreOp.Store;
  61. } else {
  62. colorAttachment.loadOp = GPULoadOp.Load;
  63. }
  64. if ( renderer.autoClearDepth === true ) {
  65. depthStencilAttachment.depthClearValue = renderer._clearDepth;
  66. depthStencilAttachment.depthLoadOp = GPULoadOp.Clear;
  67. } else {
  68. depthStencilAttachment.depthLoadOp = GPULoadOp.Load;
  69. }
  70. if ( renderer.autoClearStencil === true ) {
  71. depthStencilAttachment.stencilClearValue = renderer._clearStencil;
  72. depthStencilAttachment.stencilLoadOp = GPULoadOp.Clear;
  73. } else {
  74. depthStencilAttachment.stencilLoadOp = GPULoadOp.Load;
  75. }
  76. } else {
  77. colorAttachment.loadOp = GPULoadOp.Load;
  78. depthStencilAttachment.depthLoadOp = GPULoadOp.Load;
  79. depthStencilAttachment.stencilLoadOp = GPULoadOp.Load;
  80. }
  81. this.forceClear = false;
  82. }
  83. }
  84. export default WebGPUBackground;