Source: objects/lights/SpotLightShadow.js

  1. import { WEBGL_TEXTURE_FILTER, WEBGL_PIXEL_FORMAT, WEBGL_PIXEL_TYPE, ATTACHMENT, WEBGL_COMPARE_FUNC } from '../../const.js';
  2. import { Texture2D } from '../../texture/Texture2D.js';
  3. import { LightShadow } from './LightShadow.js';
  4. import { RenderTarget2D } from '../../render/RenderTarget2D.js';
  5. import { Vector3 } from '../../math/Vector3.js';
  6. /**
  7. * This is used internally by SpotLights for calculating shadows.
  8. * @constructor
  9. * @hideconstructor
  10. * @memberof zen3d
  11. * @extends zen3d.LightShadow
  12. */
  13. function SpotLightShadow() {
  14. LightShadow.call(this);
  15. this.renderTarget = new RenderTarget2D(this.mapSize.x, this.mapSize.y);
  16. var map = this.renderTarget.texture;
  17. map.generateMipmaps = false;
  18. map.minFilter = WEBGL_TEXTURE_FILTER.LINEAR;
  19. this.map = map;
  20. this.depthMap = null;
  21. this._lookTarget = new Vector3();
  22. this._up = new Vector3(0, 1, 0);
  23. }
  24. SpotLightShadow.prototype = Object.assign(Object.create(LightShadow.prototype), {
  25. constructor: SpotLightShadow,
  26. update: function(light) {
  27. this._updateCamera(light);
  28. this._updateMatrix();
  29. // TODO check size change, remove this from loop
  30. if (this.mapSize.x !== this.renderTarget.width || this.mapSize.y !== this.renderTarget.height) {
  31. this.renderTarget.resize(this.mapSize.x, this.mapSize.y);
  32. }
  33. },
  34. _updateCamera: function(light) {
  35. var camera = this.camera;
  36. var lookTarget = this._lookTarget;
  37. // set camera position and lookAt(rotation)
  38. light.getWorldDirection(this._lookTarget);
  39. camera.position.setFromMatrixPosition(light.worldMatrix);
  40. lookTarget.set(lookTarget.x + camera.position.x, lookTarget.y + camera.position.y, lookTarget.z + camera.position.z);
  41. camera.lookAt(lookTarget, this._up);
  42. // update view matrix
  43. camera.updateMatrix();
  44. // update projection
  45. // TODO distance should be custom?
  46. camera.setPerspective(light.angle * 2, 1, this.cameraNear, this.cameraFar);
  47. },
  48. _updateMatrix: function() {
  49. var matrix = this.matrix;
  50. var camera = this.camera;
  51. // matrix * 0.5 + 0.5, after identity, range is 0 ~ 1 instead of -1 ~ 1
  52. matrix.set(
  53. 0.5, 0.0, 0.0, 0.5,
  54. 0.0, 0.5, 0.0, 0.5,
  55. 0.0, 0.0, 0.5, 0.5,
  56. 0.0, 0.0, 0.0, 1.0
  57. );
  58. matrix.multiply(camera.projectionMatrix);
  59. matrix.multiply(camera.viewMatrix);
  60. },
  61. _initDepthMap: function() {
  62. var depthTexture = new Texture2D();
  63. depthTexture.type = WEBGL_PIXEL_TYPE.FLOAT_32_UNSIGNED_INT_24_8_REV;
  64. depthTexture.format = WEBGL_PIXEL_FORMAT.DEPTH_STENCIL;
  65. depthTexture.internalformat = WEBGL_PIXEL_FORMAT.DEPTH32F_STENCIL8;
  66. depthTexture.magFilter = WEBGL_TEXTURE_FILTER.LINEAR;
  67. depthTexture.minFilter = WEBGL_TEXTURE_FILTER.LINEAR;
  68. depthTexture.compare = WEBGL_COMPARE_FUNC.LESS;
  69. depthTexture.generateMipmaps = false;
  70. this.renderTarget.attach(
  71. depthTexture,
  72. ATTACHMENT.DEPTH_STENCIL_ATTACHMENT
  73. );
  74. this.depthMap = depthTexture;
  75. }
  76. });
  77. export { SpotLightShadow };