-
Notifications
You must be signed in to change notification settings - Fork 46
/
material.ts
131 lines (114 loc) · 3.63 KB
/
material.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 { DRAW_MODES, BLEND_MODES } from "@pixi/constants"
import { State, Renderer, Program } from "@pixi/core"
import { Mesh3D } from "../mesh/mesh"
import { MaterialRenderSortType } from "./material-render-sort-type"
import { MeshShader } from "../mesh/mesh-shader"
/**
* Materials are used to render a mesh with a specific visual appearance.
*/
export class Material {
protected _renderSortType = MaterialRenderSortType.opaque
protected _shader?: MeshShader
/** State used to render a mesh. */
state = Object.assign(new State(), {
culling: true, clockwiseFrontFace: false, depthTest: true
})
/** Draw mode used to render a mesh. */
drawMode = DRAW_MODES.TRIANGLES
/**
* Sort type used to render a mesh. Transparent materials will be rendered
* after opaque materials.
*/
renderSortType = MaterialRenderSortType.opaque
/**
* Value indicating if writing into the depth buffer is enabled or disabled.
* Depth mask feature is only available in PixiJS 6.0+ and won't have any
* effects in previous versions.
*/
get depthMask() {
return this.state.depthMask
}
set depthMask(value: boolean) {
this.state.depthMask = value
}
/**
* Value indicating if the material is double sided. When set to true, the
* culling state will be set to false.
*/
get doubleSided() {
return !this.state.culling
}
set doubleSided(value: boolean) {
this.state.culling = !value
}
/** Blend mode used to render a mesh. */
get blendMode() {
return this.state.blendMode
}
set blendMode(value: BLEND_MODES) {
this.state.blendMode = value
}
/**
* Creates a shader used to render the specified mesh.
* @param mesh The mesh to create the shader for.
* @param renderer The renderer to use.
*/
createShader(mesh: Mesh3D, renderer: Renderer): MeshShader | undefined {
return undefined
}
/**
* Updates the uniforms for the specified shader.
* @param mesh The mesh used for updating the uniforms.
* @param shader The shader to update.
*/
updateUniforms?(mesh: Mesh3D, shader: MeshShader): void { }
/**
* Destroys the material and it's used resources.
*/
destroy() { }
/**
* Returns a value indicating if this material supports instancing.
*/
get isInstancingSupported() {
return false
}
/**
* Creates a new instanced version of this material.
*/
createInstance(): unknown {
return undefined
}
/**
* Renders the specified mesh.
* @param mesh The mesh to render.
* @param renderer The renderer to use.
*/
render(mesh: Mesh3D, renderer: Renderer) {
if (!this._shader) {
this._shader = this.createShader(mesh, renderer)
if (!this._shader) {
// The shader couldn't be created for some reason. Just ignore it and
// try again at next render. The required assets may not have been loaded
// yet, so maybe we are waiting for those.
return
}
}
if (this.updateUniforms) {
this.updateUniforms(mesh, this._shader)
}
this._shader.render(mesh, renderer, this.state, this.drawMode)
}
/**
* Creates a new material from the specified vertex/fragment source.
* @param vertexSrc The vertex shader source.
* @param fragmentSrc The fragment shader source.
* @param updateUniforms The function which will be called for updating the
* shader uniforms.
*/
static from(vertexSrc: string, fragmentSrc: string, updateUniforms?: (mesh: Mesh3D, shader: MeshShader) => void): Material {
return Object.assign(new Material(), {
updateUniforms: updateUniforms || (() => { }),
_shader: new MeshShader(Program.from(vertexSrc, fragmentSrc)),
})
}
}