-
Notifications
You must be signed in to change notification settings - Fork 46
/
shadow-casting-light.ts
131 lines (115 loc) · 4.04 KB
/
shadow-casting-light.ts
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import { RenderTexture, Renderer } from "@pixi/core"
import { Light } from "../lighting/light"
import { LightType } from "../lighting/light-type"
import { Camera } from "../camera/camera"
import { Capabilities } from "../capabilities"
import { ShadowTexture } from "./shadow-texture"
import { ShadowMath } from "./shadow-math"
import { ShadowQuality } from "./shadow-quality"
export interface ShadowCastingLightOptions {
/**
* The quality (precision) of the shadow. If the quality is not supported by
* current platform, a lower quality will be selected instead.
*/
quality?: ShadowQuality
/**
* The size (both width and height) in pixels for the shadow texture.
* Increasing the size will improve the quality of the shadow.
*/
shadowTextureSize?: number
}
/**
* Contains the required components used for rendering a shadow casted by a light.
*/
export class ShadowCastingLight {
private _shadowTexture: RenderTexture
private _filterTexture: RenderTexture
private _lightViewProjection = new Float32Array(16)
/** The softness of the edges for the shadow. */
softness = 0
/**
* The area in units of the shadow when using directional lights. Reducing
* the area will improve the quality of the shadow.
*/
shadowArea = 50
/** The light view projection matrix. */
get lightViewProjection() {
return this._lightViewProjection
}
/** The camera to follow when using directional lights. */
camera?: Camera
/**
* Value indicating if the shadow should follow the specified camera. If the
* camera is not set, the main camera will be used as default. Only available
* when using directional lights.
*/
followCamera = true
/**
* The rendered shadow texture.
*/
get shadowTexture() {
return this._shadowTexture
}
/**
* The rendered filter texture.
*/
get filterTexture() {
return this._filterTexture
}
/**
* Creates a new shadow casting light used for rendering a shadow texture.
* @param renderer The renderer to use.
* @param light The light which is casting the shadow.
* @param options The options to use when creating the shadow texture.
*/
constructor(public renderer: Renderer, public light: Light, options?: ShadowCastingLightOptions) {
if (light.type === LightType.point) {
throw new Error("PIXI3D: Only directional and spot lights are supported as shadow casters.")
}
const { shadowTextureSize = 1024, quality = ShadowQuality.medium } = options || {}
this._shadowTexture = ShadowTexture.create(renderer, shadowTextureSize, quality)
this._shadowTexture.baseTexture.framebuffer.addDepthTexture()
this._filterTexture = ShadowTexture.create(renderer, shadowTextureSize, quality)
}
/**
* Destroys the shadow casting light and it's used resources.
*/
destroy() {
this._shadowTexture.destroy(true)
this._filterTexture.destroy(true)
}
/**
* Clears the rendered shadow texture.
*/
clear() {
this.renderer.renderTexture.bind(this._shadowTexture)
this.renderer.renderTexture.clear([0, 0, 0, 0], this.renderer.gl.COLOR_BUFFER_BIT | this.renderer.gl.DEPTH_BUFFER_BIT)
this.renderer.renderTexture.bind(undefined)
}
/**
* Updates the light view projection matrix.
*/
updateLightViewProjection() {
if (this.light.type === LightType.directional) {
ShadowMath.calculateDirectionalLightViewProjection(this)
} else if (this.light.type === LightType.spot) {
ShadowMath.calculateSpotLightViewProjection(this)
}
}
/**
* Returns a value indicating if medium quality (16-bit precision) shadows is
* supported by current platform.
* @param renderer The renderer to use.
*/
static isMediumQualitySupported(renderer: Renderer) {
return Capabilities.isHalfFloatFramebufferSupported(renderer)
}
/**
* Returns a value indicating if high quality (32-bit precision) shadows is
* supported by current platform.
* @param renderer The renderer to use.
*/
static isHighQualitySupported(renderer: Renderer) {
return Capabilities.isFloatFramebufferSupported(renderer)
}
}