CSMHelper.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import { Group, Mesh, LineSegments, BufferGeometry, LineBasicMaterial, Box3Helper, Box3, PlaneBufferGeometry, MeshBasicMaterial, BufferAttribute } from '../../../build/three.module.js';
  2. class CSMHelper extends Group {
  3. constructor( csm ) {
  4. super();
  5. this.csm = csm;
  6. const indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] );
  7. const positions = new Float32Array( 24 );
  8. const frustumGeometry = new BufferGeometry();
  9. frustumGeometry.setIndex( new BufferAttribute( indices, 1 ) );
  10. frustumGeometry.setAttribute( 'position', new BufferAttribute( positions, 3, false ) );
  11. const frustumLines = new LineSegments( frustumGeometry, new LineBasicMaterial() );
  12. this.add( frustumLines );
  13. this.frustumLines = frustumLines;
  14. this.cascadeLines = [];
  15. this.cascadePlanes = [];
  16. this.shadowLines = [];
  17. }
  18. update() {
  19. const csm = this.csm;
  20. const camera = csm.camera;
  21. const cascades = csm.cascades;
  22. const mainFrustum = csm.mainFrustum;
  23. const frustums = csm.frustums;
  24. const lights = csm.lights;
  25. const frustumLines = this.frustumLines;
  26. const frustumLinePositions = frustumLines.geometry.getAttribute( 'position' );
  27. const cascadeLines = this.cascadeLines;
  28. const cascadePlanes = this.cascadePlanes;
  29. const shadowLines = this.shadowLines;
  30. while( cascadeLines.length > cascades ) {
  31. this.remove( cascadeLines.pop() );
  32. this.remove( cascadePlanes.pop() );
  33. this.remove( shadowLines.pop() );
  34. }
  35. while( cascadeLines.length < cascades ) {
  36. const cascadeLine = new Box3Helper( new Box3(), 0xffffff );
  37. const cascadePlane = new Mesh( new PlaneBufferGeometry(), new MeshBasicMaterial( { transparent: true, opacity: 0.1, depthWrite: false } ) );
  38. const shadowLineGroup = new Group();
  39. const shadowLine = new Box3Helper( new Box3(), 0xffff00 );
  40. shadowLineGroup.add( shadowLine );
  41. this.add( cascadeLine );
  42. this.add( cascadePlane );
  43. this.add( shadowLineGroup );
  44. cascadeLines.push( cascadeLine );
  45. cascadePlanes.push( cascadePlane );
  46. shadowLines.push( shadowLineGroup );
  47. }
  48. for ( let i = 0; i < cascades; i ++ ) {
  49. const frustum = frustums[ i ];
  50. const light = lights[ i ];
  51. const shadowCam = light.shadow.camera;
  52. const farVerts = frustum.vertices.far;
  53. const cascadeLine = cascadeLines[ i ];
  54. const cascadePlane = cascadePlanes[ i ];
  55. const shadowLineGroup = shadowLines[ i ];
  56. const shadowLine = shadowLineGroup.children[ 0 ];
  57. cascadeLine.box.min.copy( farVerts[ 2 ] );
  58. cascadeLine.box.max.copy( farVerts[ 0 ] );
  59. cascadeLine.box.max.z += 1e-4;
  60. cascadePlane.position.addVectors( farVerts[ 0 ], farVerts[ 2 ] );
  61. cascadePlane.position.multiplyScalar( 0.5 );
  62. cascadePlane.scale.subVectors( farVerts[ 0 ], farVerts[ 2 ] );
  63. cascadePlane.scale.z = 1e-4;
  64. this.remove( shadowLineGroup );
  65. shadowCam.matrixWorld.decompose( shadowLineGroup.position, shadowLineGroup.quaternion, shadowLineGroup.scale );
  66. shadowCam.updateMatrixWorld( true );
  67. this.attach( shadowLineGroup );
  68. shadowLine.box.min.set( shadowCam.bottom, shadowCam.left, shadowCam.near );
  69. shadowLine.box.max.set( shadowCam.top, shadowCam.right, shadowCam.far );
  70. }
  71. const nearVerts = mainFrustum.vertices.near;
  72. const farVerts = mainFrustum.vertices.far;
  73. frustumLinePositions.setXYZ( 0, farVerts[ 0 ].x, farVerts[ 0 ].y, farVerts[ 0 ].z );
  74. frustumLinePositions.setXYZ( 1, farVerts[ 3 ].x, farVerts[ 3 ].y, farVerts[ 3 ].z );
  75. frustumLinePositions.setXYZ( 2, farVerts[ 2 ].x, farVerts[ 2 ].y, farVerts[ 2 ].z );
  76. frustumLinePositions.setXYZ( 3, farVerts[ 1 ].x, farVerts[ 1 ].y, farVerts[ 1 ].z );
  77. frustumLinePositions.setXYZ( 4, nearVerts[ 0 ].x, nearVerts[ 0 ].y, nearVerts[ 0 ].z );
  78. frustumLinePositions.setXYZ( 5, nearVerts[ 3 ].x, nearVerts[ 3 ].y, nearVerts[ 3 ].z );
  79. frustumLinePositions.setXYZ( 6, nearVerts[ 2 ].x, nearVerts[ 2 ].y, nearVerts[ 2 ].z );
  80. frustumLinePositions.setXYZ( 7, nearVerts[ 1 ].x, nearVerts[ 1 ].y, nearVerts[ 1 ].z );
  81. frustumLinePositions.needsUpdate = true;
  82. this.position.copy( camera.position );
  83. this.quaternion.copy( camera.quaternion );
  84. this.scale.copy( camera.scale );
  85. }
  86. }
  87. export { CSMHelper };