File size: 2,609 Bytes
2b7aae2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { Matrix4 } from '../math/Matrix4.js';
import { Vector2 } from '../math/Vector2.js';
import { Vector3 } from '../math/Vector3.js';
import { Vector4 } from '../math/Vector4.js';
import { Frustum } from '../math/Frustum.js';

const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
const _lightPositionWorld = /*@__PURE__*/ new Vector3();
const _lookTarget = /*@__PURE__*/ new Vector3();

class LightShadow {
	constructor(camera) {
		this.camera = camera;

		this.bias = 0;
		this.normalBias = 0;
		this.radius = 1;
		this.blurSamples = 8;

		this.mapSize = new Vector2(512, 512);

		this.map = null;
		this.mapPass = null;
		this.matrix = new Matrix4();

		this.autoUpdate = true;
		this.needsUpdate = false;

		this._frustum = new Frustum();
		this._frameExtents = new Vector2(1, 1);

		this._viewportCount = 1;

		this._viewports = [new Vector4(0, 0, 1, 1)];
	}

	getViewportCount() {
		return this._viewportCount;
	}

	getFrustum() {
		return this._frustum;
	}

	updateMatrices(light) {
		const shadowCamera = this.camera;
		const shadowMatrix = this.matrix;

		_lightPositionWorld.setFromMatrixPosition(light.matrixWorld);
		shadowCamera.position.copy(_lightPositionWorld);

		_lookTarget.setFromMatrixPosition(light.target.matrixWorld);
		shadowCamera.lookAt(_lookTarget);
		shadowCamera.updateMatrixWorld();

		_projScreenMatrix.multiplyMatrices(shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse);
		this._frustum.setFromProjectionMatrix(_projScreenMatrix);

		shadowMatrix.set(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0);

		shadowMatrix.multiply(shadowCamera.projectionMatrix);
		shadowMatrix.multiply(shadowCamera.matrixWorldInverse);
	}

	getViewport(viewportIndex) {
		return this._viewports[viewportIndex];
	}

	getFrameExtents() {
		return this._frameExtents;
	}

	dispose() {
		if (this.map) {
			this.map.dispose();
		}

		if (this.mapPass) {
			this.mapPass.dispose();
		}
	}

	copy(source) {
		this.camera = source.camera.clone();

		this.bias = source.bias;
		this.radius = source.radius;

		this.mapSize.copy(source.mapSize);

		return this;
	}

	clone() {
		return new this.constructor().copy(this);
	}

	toJSON() {
		const object = {};

		if (this.bias !== 0) object.bias = this.bias;
		if (this.normalBias !== 0) object.normalBias = this.normalBias;
		if (this.radius !== 1) object.radius = this.radius;
		if (this.mapSize.x !== 512 || this.mapSize.y !== 512) object.mapSize = this.mapSize.toArray();

		object.camera = this.camera.toJSON(false).object;
		delete object.camera.matrix;

		return object;
	}
}

export { LightShadow };