WebGPUBackground.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import { GPULoadOp, GPUStoreOp } from './constants.js';
  2. import { Color, Mesh, BoxGeometry, BackSide } from 'three';
  3. import { context, transformDirection, positionWorld, modelWorldMatrix } from 'three-nodes/Nodes.js';
  4. import MeshBasicNodeMaterial from 'three-nodes/materials/MeshBasicNodeMaterial.js';
  5. let _clearAlpha;
  6. const _clearColor = new Color();
  7. class WebGPUBackground {
  8. constructor( renderer ) {
  9. this.renderer = renderer;
  10. this.boxMesh = null;
  11. this.forceClear = false;
  12. }
  13. clear() {
  14. this.forceClear = true;
  15. }
  16. update( renderList, scene ) {
  17. const renderer = this.renderer;
  18. const background = ( scene.isScene === true ) ? scene.backgroundNode || scene.background : null;
  19. let forceClear = this.forceClear;
  20. if ( background === null ) {
  21. // no background settings, use clear color configuration from the renderer
  22. _clearColor.copy( renderer._clearColor );
  23. _clearAlpha = renderer._clearAlpha;
  24. } else if ( background.isColor === true ) {
  25. // background is an opaque color
  26. _clearColor.copy( background );
  27. _clearAlpha = 1;
  28. forceClear = true;
  29. } else if ( background.isNode === true ) {
  30. _clearColor.copy( renderer._clearColor );
  31. _clearAlpha = renderer._clearAlpha;
  32. let boxMesh = this.boxMesh;
  33. if ( boxMesh === null ) {
  34. const colorNode = context( background, {
  35. uvNode: transformDirection( positionWorld, modelWorldMatrix )
  36. } );
  37. const nodeMaterial = new MeshBasicNodeMaterial();
  38. nodeMaterial.colorNode = colorNode;
  39. nodeMaterial.side = BackSide;
  40. nodeMaterial.depthTest = false;
  41. nodeMaterial.depthWrite = false;
  42. nodeMaterial.fog = false;
  43. this.boxMesh = boxMesh = new Mesh( new BoxGeometry( 1, 1, 1 ), nodeMaterial );
  44. boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
  45. this.matrixWorld.copyPosition( camera.matrixWorld );
  46. };
  47. }
  48. renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
  49. } else {
  50. console.error( 'THREE.WebGPURenderer: Unsupported background configuration.', background );
  51. }
  52. // configure render pass descriptor
  53. const renderPassDescriptor = renderer._renderPassDescriptor;
  54. const colorAttachment = renderPassDescriptor.colorAttachments[ 0 ];
  55. const depthStencilAttachment = renderPassDescriptor.depthStencilAttachment;
  56. if ( renderer.autoClear === true || forceClear === true ) {
  57. if ( renderer.autoClearColor === true ) {
  58. _clearColor.multiplyScalar( _clearAlpha );
  59. colorAttachment.clearValue = { r: _clearColor.r, g: _clearColor.g, b: _clearColor.b, a: _clearAlpha };
  60. colorAttachment.loadOp = GPULoadOp.Clear;
  61. colorAttachment.storeOp = GPUStoreOp.Store;
  62. } else {
  63. colorAttachment.loadOp = GPULoadOp.Load;
  64. }
  65. if ( renderer.autoClearDepth === true ) {
  66. depthStencilAttachment.depthClearValue = renderer._clearDepth;
  67. depthStencilAttachment.depthLoadOp = GPULoadOp.Clear;
  68. } else {
  69. depthStencilAttachment.depthLoadOp = GPULoadOp.Load;
  70. }
  71. if ( renderer.autoClearStencil === true ) {
  72. depthStencilAttachment.stencilClearValue = renderer._clearStencil;
  73. depthStencilAttachment.stencilLoadOp = GPULoadOp.Clear;
  74. } else {
  75. depthStencilAttachment.stencilLoadOp = GPULoadOp.Load;
  76. }
  77. } else {
  78. colorAttachment.loadOp = GPULoadOp.Load;
  79. depthStencilAttachment.depthLoadOp = GPULoadOp.Load;
  80. depthStencilAttachment.stencilLoadOp = GPULoadOp.Load;
  81. }
  82. this.forceClear = false;
  83. }
  84. }
  85. export default WebGPUBackground;