@openspecui/web 0.9.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/BufferResource-CVUoegR6.js +185 -0
- package/dist/assets/CanvasRenderer-BEIcB8i1.js +1 -0
- package/dist/assets/Filter-Bu_qhr6H.js +1 -0
- package/dist/assets/RenderTargetSystem-DWouFDxU.js +172 -0
- package/dist/assets/WebGLRenderer-6FH_N1FV.js +156 -0
- package/dist/assets/WebGPURenderer-B8sJk3Sv.js +41 -0
- package/dist/assets/browserAll-CLKeV1yb.js +14 -0
- package/dist/assets/gemini-Bk-V9kKu.png +0 -0
- package/dist/assets/{index-Bp00uZNc.js → index-BE5-y0_g.js} +1 -1
- package/{dist-ssg/client/assets/index-CCfVkFzN.js → dist/assets/index-BPCTI2mG.js} +1 -1
- package/dist/assets/{index-BsTieXqQ.js → index-BRp8MJ9v.js} +1 -1
- package/dist/assets/{index-8c6bEJ99.js → index-BlZ-sasH.js} +1 -1
- package/dist/assets/{index-Bafja8o4.js → index-Bp_dnlLF.js} +1 -1
- package/{dist-ssg/client/assets/index-ftYom_wU.js → dist/assets/index-BtNuxyw4.js} +1 -1
- package/dist/assets/index-Bv7pWR8R.js +7 -0
- package/{dist-ssg/client/assets/index-D3mXuuih.js → dist/assets/index-Byr3HkRi.js} +1 -1
- package/dist/assets/index-CEHMo0EU.js +1385 -0
- package/dist/assets/{index-eA_XNQ_L.js → index-CEKSUzvw.js} +1 -1
- package/dist/assets/index-CEf9wXLh.css +1 -0
- package/{dist-ssg/client/assets/index-ArhptQw0.js → dist/assets/index-CX13iBBs.js} +1 -1
- package/dist/assets/index-CoOT7eZ9.js +1 -0
- package/{dist-ssg/client/assets/index-B1hpa--1.js → dist/assets/index-D4AU46yO.js} +1 -1
- package/dist/assets/{index-BvGAWAqS.js → index-DXRZmZm8.js} +1 -1
- package/{dist-ssg/client/assets/index-AbWe21oh.js → dist/assets/index-eQZwF8qE.js} +1 -1
- package/dist/assets/{index-gvPT4BlL.js → index-mWXhCp9j.js} +1 -1
- package/dist/assets/webworkerAll-DjWoTx9g.js +83 -0
- package/dist/index.html +2 -2
- package/dist-ssg/client/.vite/ssr-manifest.json +3094 -504
- package/dist-ssg/client/assets/BufferResource-CVUoegR6.js +185 -0
- package/dist-ssg/client/assets/CanvasRenderer-BEIcB8i1.js +1 -0
- package/dist-ssg/client/assets/Filter-Bu_qhr6H.js +1 -0
- package/dist-ssg/client/assets/RenderTargetSystem-DWouFDxU.js +172 -0
- package/dist-ssg/client/assets/WebGLRenderer-6FH_N1FV.js +156 -0
- package/dist-ssg/client/assets/WebGPURenderer-B8sJk3Sv.js +41 -0
- package/dist-ssg/client/assets/browserAll-CLKeV1yb.js +14 -0
- package/dist-ssg/client/assets/gemini-Bk-V9kKu.png +0 -0
- package/dist-ssg/client/assets/{index-Bp00uZNc.js → index-BE5-y0_g.js} +1 -1
- package/{dist/assets/index-CCfVkFzN.js → dist-ssg/client/assets/index-BPCTI2mG.js} +1 -1
- package/dist-ssg/client/assets/{index-BsTieXqQ.js → index-BRp8MJ9v.js} +1 -1
- package/dist-ssg/client/assets/{index-8c6bEJ99.js → index-BlZ-sasH.js} +1 -1
- package/dist-ssg/client/assets/{index-Bafja8o4.js → index-Bp_dnlLF.js} +1 -1
- package/{dist/assets/index-ftYom_wU.js → dist-ssg/client/assets/index-BtNuxyw4.js} +1 -1
- package/dist-ssg/client/assets/index-Bv7pWR8R.js +7 -0
- package/{dist/assets/index-D3mXuuih.js → dist-ssg/client/assets/index-Byr3HkRi.js} +1 -1
- package/dist-ssg/client/assets/index-CEHMo0EU.js +1385 -0
- package/dist-ssg/client/assets/{index-eA_XNQ_L.js → index-CEKSUzvw.js} +1 -1
- package/dist-ssg/client/assets/index-CEf9wXLh.css +1 -0
- package/{dist/assets/index-ArhptQw0.js → dist-ssg/client/assets/index-CX13iBBs.js} +1 -1
- package/dist-ssg/client/assets/index-CoOT7eZ9.js +1 -0
- package/{dist/assets/index-B1hpa--1.js → dist-ssg/client/assets/index-D4AU46yO.js} +1 -1
- package/dist-ssg/client/assets/{index-BvGAWAqS.js → index-DXRZmZm8.js} +1 -1
- package/{dist/assets/index-AbWe21oh.js → dist-ssg/client/assets/index-eQZwF8qE.js} +1 -1
- package/dist-ssg/client/assets/{index-gvPT4BlL.js → index-mWXhCp9j.js} +1 -1
- package/dist-ssg/client/assets/webworkerAll-DjWoTx9g.js +83 -0
- package/dist-ssg/client/index.html +2 -2
- package/dist-ssg/server/assets/BufferResource-BXrsGVSz.js +592 -0
- package/dist-ssg/server/assets/CanvasRenderer-D9aMd7WV.js +1530 -0
- package/dist-ssg/server/assets/Filter-ClU0-pLL.js +80 -0
- package/dist-ssg/server/assets/RenderTargetSystem-CVz6i60H.js +3037 -0
- package/dist-ssg/server/assets/WebGLRenderer-B0I5TP5d.js +3887 -0
- package/dist-ssg/server/assets/WebGPURenderer-DCgUFny7.js +2146 -0
- package/dist-ssg/server/assets/browserAll-BixK1BYs.js +2691 -0
- package/dist-ssg/server/assets/{index-BUANIFyF.js → index-3uSTc-o9.js} +3 -1
- package/dist-ssg/server/assets/{index-D0JVKGRJ.js → index-8uE7RyRi.js} +3 -1
- package/dist-ssg/server/assets/{index-DCGDP0cs.js → index-BDzDVVaf.js} +2 -0
- package/dist-ssg/server/assets/{index-oPcprgZH.js → index-BkJYfA64.js} +3 -1
- package/dist-ssg/server/assets/{index-CAP0cmVO.js → index-BvGNqnLD.js} +3 -1
- package/dist-ssg/server/assets/{index-DsfT46da.js → index-BvURgefh.js} +3 -1
- package/dist-ssg/server/assets/{index-Dk9q2o0C.js → index-C2CuXbSQ.js} +3 -1
- package/dist-ssg/server/assets/{index-Cmnd0jiw.js → index-C3RtR5EA.js} +3 -1
- package/dist-ssg/server/assets/{index-CFKaffPZ.js → index-CZtnphnE.js} +3 -1
- package/dist-ssg/server/assets/{index-D6n8WPGB.js → index-D0DRToHj.js} +3 -1
- package/dist-ssg/server/assets/{index-mJoWrrNO.js → index-D5MdLWau.js} +3 -1
- package/dist-ssg/server/assets/{index-Brcpp_nj.js → index-DBYODvy4.js} +3 -1
- package/dist-ssg/server/assets/{index-DYmgiM6_.js → index-DL23PkQi.js} +3 -1
- package/dist-ssg/server/assets/{index-CnRKREoz.js → index-DfcLdBOi.js} +3 -1
- package/dist-ssg/server/assets/{index-Bzw5T-vd.js → index-O2XMojWG.js} +3 -1
- package/dist-ssg/server/assets/init-CnkBvt-J.js +666 -0
- package/dist-ssg/server/assets/webworkerAll-DNiMFaVV.js +12 -0
- package/dist-ssg/server/entry-server.js +87120 -34846
- package/package.json +23 -5
- package/dist/assets/index-D-Urq2hl.css +0 -1
- package/dist/assets/index-DFOLYN6W.js +0 -1
- package/dist/assets/index-DpxkOmNJ.js +0 -7
- package/dist/assets/index-YZ-iXB95.js +0 -309
- package/dist-ssg/client/assets/index-D-Urq2hl.css +0 -1
- package/dist-ssg/client/assets/index-DFOLYN6W.js +0 -1
- package/dist-ssg/client/assets/index-DpxkOmNJ.js +0 -7
- package/dist-ssg/client/assets/index-YZ-iXB95.js +0 -309
|
@@ -0,0 +1,3887 @@
|
|
|
1
|
+
import { X as DOMAdapter, r as State, y as ExtensionType, ae as GCManagedHash, Q as BufferUsage, D as warn, J as getAttributeInfoFromFormat, u as GlProgram, S as Shader, z as Texture, A as Geometry, ai as TextureSource, aK as checkMaxIfStatementsInShader, K as STENCIL_MODES, aB as Rectangle, a6 as CanvasSource, ah as CLEAR, U as UniformGroup, M as Matrix, aL as compileHighShaderGlProgram, aM as colorBitGl, aN as generateTextureBatchBitGl, aO as roundPixelsBitGl, aP as getBatchSamplersUniformGroup, a7 as AbstractRenderer, R as RendererType, H as extensions } from "../entry-server.js";
|
|
2
|
+
import { e as ensureAttributes, G as GpuStencilModesToPixi, c as createUboSyncFunction, b as uboSyncFunctionsSTD40, U as UboSystem, B as BufferResource, d as uniformParsers, f as localUniformBitGl, g as textureBitGl } from "./BufferResource-BXrsGVSz.js";
|
|
3
|
+
import { R as RenderTargetSystem, S as SharedSystems, d as SharedRenderPipes } from "./RenderTargetSystem-CVz6i60H.js";
|
|
4
|
+
import "util";
|
|
5
|
+
import "crypto";
|
|
6
|
+
import "async_hooks";
|
|
7
|
+
import "stream";
|
|
8
|
+
import "process";
|
|
9
|
+
import "buffer";
|
|
10
|
+
import "node:process";
|
|
11
|
+
import "node:path";
|
|
12
|
+
import "node:url";
|
|
13
|
+
import "./Filter-ClU0-pLL.js";
|
|
14
|
+
function isSafari() {
|
|
15
|
+
const { userAgent } = DOMAdapter.get().getNavigator();
|
|
16
|
+
return /^((?!chrome|android).)*safari/i.test(userAgent);
|
|
17
|
+
}
|
|
18
|
+
class GlBatchAdaptor {
|
|
19
|
+
constructor() {
|
|
20
|
+
this._tempState = State.for2d();
|
|
21
|
+
this._didUploadHash = {};
|
|
22
|
+
}
|
|
23
|
+
init(batcherPipe) {
|
|
24
|
+
batcherPipe.renderer.runners.contextChange.add(this);
|
|
25
|
+
}
|
|
26
|
+
contextChange() {
|
|
27
|
+
this._didUploadHash = {};
|
|
28
|
+
}
|
|
29
|
+
start(batchPipe, geometry, shader) {
|
|
30
|
+
const renderer = batchPipe.renderer;
|
|
31
|
+
const didUpload = this._didUploadHash[shader.uid];
|
|
32
|
+
renderer.shader.bind(shader, didUpload);
|
|
33
|
+
if (!didUpload) {
|
|
34
|
+
this._didUploadHash[shader.uid] = true;
|
|
35
|
+
}
|
|
36
|
+
renderer.shader.updateUniformGroup(renderer.globalUniforms.uniformGroup);
|
|
37
|
+
renderer.geometry.bind(geometry, shader.glProgram);
|
|
38
|
+
}
|
|
39
|
+
execute(batchPipe, batch) {
|
|
40
|
+
const renderer = batchPipe.renderer;
|
|
41
|
+
this._tempState.blendMode = batch.blendMode;
|
|
42
|
+
renderer.state.set(this._tempState);
|
|
43
|
+
const textures = batch.textures.textures;
|
|
44
|
+
for (let i = 0; i < batch.textures.count; i++) {
|
|
45
|
+
renderer.texture.bind(textures[i], i);
|
|
46
|
+
}
|
|
47
|
+
renderer.geometry.draw(batch.topology, batch.size, batch.start);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
GlBatchAdaptor.extension = {
|
|
51
|
+
type: [
|
|
52
|
+
ExtensionType.WebGLPipesAdaptor
|
|
53
|
+
],
|
|
54
|
+
name: "batch"
|
|
55
|
+
};
|
|
56
|
+
var BUFFER_TYPE = /* @__PURE__ */ ((BUFFER_TYPE2) => {
|
|
57
|
+
BUFFER_TYPE2[BUFFER_TYPE2["ELEMENT_ARRAY_BUFFER"] = 34963] = "ELEMENT_ARRAY_BUFFER";
|
|
58
|
+
BUFFER_TYPE2[BUFFER_TYPE2["ARRAY_BUFFER"] = 34962] = "ARRAY_BUFFER";
|
|
59
|
+
BUFFER_TYPE2[BUFFER_TYPE2["UNIFORM_BUFFER"] = 35345] = "UNIFORM_BUFFER";
|
|
60
|
+
return BUFFER_TYPE2;
|
|
61
|
+
})(BUFFER_TYPE || {});
|
|
62
|
+
class GlBuffer {
|
|
63
|
+
constructor(buffer, type) {
|
|
64
|
+
this._lastBindBaseLocation = -1;
|
|
65
|
+
this._lastBindCallId = -1;
|
|
66
|
+
this.buffer = buffer || null;
|
|
67
|
+
this.updateID = -1;
|
|
68
|
+
this.byteLength = -1;
|
|
69
|
+
this.type = type;
|
|
70
|
+
}
|
|
71
|
+
destroy() {
|
|
72
|
+
this.buffer = null;
|
|
73
|
+
this.updateID = -1;
|
|
74
|
+
this.byteLength = -1;
|
|
75
|
+
this.type = -1;
|
|
76
|
+
this._lastBindBaseLocation = -1;
|
|
77
|
+
this._lastBindCallId = -1;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
class GlBufferSystem {
|
|
81
|
+
/**
|
|
82
|
+
* @param {Renderer} renderer - The renderer this System works for.
|
|
83
|
+
*/
|
|
84
|
+
constructor(renderer) {
|
|
85
|
+
this._boundBufferBases = /* @__PURE__ */ Object.create(null);
|
|
86
|
+
this._minBaseLocation = 0;
|
|
87
|
+
this._nextBindBaseIndex = this._minBaseLocation;
|
|
88
|
+
this._bindCallId = 0;
|
|
89
|
+
this._renderer = renderer;
|
|
90
|
+
this._managedBuffers = new GCManagedHash({
|
|
91
|
+
renderer,
|
|
92
|
+
type: "resource",
|
|
93
|
+
onUnload: this.onBufferUnload.bind(this),
|
|
94
|
+
name: "glBuffer"
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/** @ignore */
|
|
98
|
+
destroy() {
|
|
99
|
+
this._managedBuffers.destroy();
|
|
100
|
+
this._renderer = null;
|
|
101
|
+
this._gl = null;
|
|
102
|
+
this._boundBufferBases = {};
|
|
103
|
+
}
|
|
104
|
+
/** Sets up the renderer context and necessary buffers. */
|
|
105
|
+
contextChange() {
|
|
106
|
+
this._gl = this._renderer.gl;
|
|
107
|
+
this.destroyAll(true);
|
|
108
|
+
this._maxBindings = this._renderer.limits.maxUniformBindings;
|
|
109
|
+
}
|
|
110
|
+
getGlBuffer(buffer) {
|
|
111
|
+
buffer._gcLastUsed = this._renderer.gc.now;
|
|
112
|
+
return buffer._gpuData[this._renderer.uid] || this.createGLBuffer(buffer);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* This binds specified buffer. On first run, it will create the webGL buffers for the context too
|
|
116
|
+
* @param buffer - the buffer to bind to the renderer
|
|
117
|
+
*/
|
|
118
|
+
bind(buffer) {
|
|
119
|
+
const { _gl: gl } = this;
|
|
120
|
+
const glBuffer = this.getGlBuffer(buffer);
|
|
121
|
+
gl.bindBuffer(glBuffer.type, glBuffer.buffer);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Binds an uniform buffer to at the given index.
|
|
125
|
+
*
|
|
126
|
+
* A cache is used so a buffer will not be bound again if already bound.
|
|
127
|
+
* @param glBuffer - the buffer to bind
|
|
128
|
+
* @param index - the base index to bind it to.
|
|
129
|
+
*/
|
|
130
|
+
bindBufferBase(glBuffer, index) {
|
|
131
|
+
const { _gl: gl } = this;
|
|
132
|
+
if (this._boundBufferBases[index] !== glBuffer) {
|
|
133
|
+
this._boundBufferBases[index] = glBuffer;
|
|
134
|
+
glBuffer._lastBindBaseLocation = index;
|
|
135
|
+
gl.bindBufferBase(gl.UNIFORM_BUFFER, index, glBuffer.buffer);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
nextBindBase(hasTransformFeedback) {
|
|
139
|
+
this._bindCallId++;
|
|
140
|
+
this._minBaseLocation = 0;
|
|
141
|
+
if (hasTransformFeedback) {
|
|
142
|
+
this._boundBufferBases[0] = null;
|
|
143
|
+
this._minBaseLocation = 1;
|
|
144
|
+
if (this._nextBindBaseIndex < 1) {
|
|
145
|
+
this._nextBindBaseIndex = 1;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
freeLocationForBufferBase(glBuffer) {
|
|
150
|
+
let freeIndex = this.getLastBindBaseLocation(glBuffer);
|
|
151
|
+
if (freeIndex >= this._minBaseLocation) {
|
|
152
|
+
glBuffer._lastBindCallId = this._bindCallId;
|
|
153
|
+
return freeIndex;
|
|
154
|
+
}
|
|
155
|
+
let loop = 0;
|
|
156
|
+
let nextIndex = this._nextBindBaseIndex;
|
|
157
|
+
while (loop < 2) {
|
|
158
|
+
if (nextIndex >= this._maxBindings) {
|
|
159
|
+
nextIndex = this._minBaseLocation;
|
|
160
|
+
loop++;
|
|
161
|
+
}
|
|
162
|
+
const curBuf = this._boundBufferBases[nextIndex];
|
|
163
|
+
if (curBuf && curBuf._lastBindCallId === this._bindCallId) {
|
|
164
|
+
nextIndex++;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
freeIndex = nextIndex;
|
|
170
|
+
this._nextBindBaseIndex = nextIndex + 1;
|
|
171
|
+
if (loop >= 2) {
|
|
172
|
+
return -1;
|
|
173
|
+
}
|
|
174
|
+
glBuffer._lastBindCallId = this._bindCallId;
|
|
175
|
+
this._boundBufferBases[freeIndex] = null;
|
|
176
|
+
return freeIndex;
|
|
177
|
+
}
|
|
178
|
+
getLastBindBaseLocation(glBuffer) {
|
|
179
|
+
const index = glBuffer._lastBindBaseLocation;
|
|
180
|
+
if (this._boundBufferBases[index] === glBuffer) {
|
|
181
|
+
return index;
|
|
182
|
+
}
|
|
183
|
+
return -1;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Binds a buffer whilst also binding its range.
|
|
187
|
+
* This will make the buffer start from the offset supplied rather than 0 when it is read.
|
|
188
|
+
* @param glBuffer - the buffer to bind
|
|
189
|
+
* @param index - the base index to bind at, defaults to 0
|
|
190
|
+
* @param offset - the offset to bind at (this is blocks of 256). 0 = 0, 1 = 256, 2 = 512 etc
|
|
191
|
+
* @param size - the size to bind at (this is blocks of 256).
|
|
192
|
+
*/
|
|
193
|
+
bindBufferRange(glBuffer, index, offset, size) {
|
|
194
|
+
const { _gl: gl } = this;
|
|
195
|
+
offset || (offset = 0);
|
|
196
|
+
index || (index = 0);
|
|
197
|
+
this._boundBufferBases[index] = null;
|
|
198
|
+
gl.bindBufferRange(gl.UNIFORM_BUFFER, index || 0, glBuffer.buffer, offset * 256, size || 256);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Will ensure the data in the buffer is uploaded to the GPU.
|
|
202
|
+
* @param {Buffer} buffer - the buffer to update
|
|
203
|
+
*/
|
|
204
|
+
updateBuffer(buffer) {
|
|
205
|
+
const { _gl: gl } = this;
|
|
206
|
+
const glBuffer = this.getGlBuffer(buffer);
|
|
207
|
+
if (buffer._updateID === glBuffer.updateID) {
|
|
208
|
+
return glBuffer;
|
|
209
|
+
}
|
|
210
|
+
glBuffer.updateID = buffer._updateID;
|
|
211
|
+
gl.bindBuffer(glBuffer.type, glBuffer.buffer);
|
|
212
|
+
const data = buffer.data;
|
|
213
|
+
const drawType = buffer.descriptor.usage & BufferUsage.STATIC ? gl.STATIC_DRAW : gl.DYNAMIC_DRAW;
|
|
214
|
+
if (data) {
|
|
215
|
+
if (glBuffer.byteLength >= data.byteLength) {
|
|
216
|
+
gl.bufferSubData(glBuffer.type, 0, data, 0, buffer._updateSize / data.BYTES_PER_ELEMENT);
|
|
217
|
+
} else {
|
|
218
|
+
glBuffer.byteLength = data.byteLength;
|
|
219
|
+
gl.bufferData(glBuffer.type, data, drawType);
|
|
220
|
+
}
|
|
221
|
+
} else {
|
|
222
|
+
glBuffer.byteLength = buffer.descriptor.size;
|
|
223
|
+
gl.bufferData(glBuffer.type, glBuffer.byteLength, drawType);
|
|
224
|
+
}
|
|
225
|
+
return glBuffer;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* dispose all WebGL resources of all managed buffers
|
|
229
|
+
* @param contextLost
|
|
230
|
+
*/
|
|
231
|
+
destroyAll(contextLost = false) {
|
|
232
|
+
this._managedBuffers.removeAll(contextLost);
|
|
233
|
+
}
|
|
234
|
+
onBufferUnload(buffer, contextLost = false) {
|
|
235
|
+
const glBuffer = buffer._gpuData[this._renderer.uid];
|
|
236
|
+
if (!glBuffer) return;
|
|
237
|
+
if (!contextLost) this._gl.deleteBuffer(glBuffer.buffer);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* creates and attaches a GLBuffer object tied to the current context.
|
|
241
|
+
* @param buffer
|
|
242
|
+
* @protected
|
|
243
|
+
*/
|
|
244
|
+
createGLBuffer(buffer) {
|
|
245
|
+
const { _gl: gl } = this;
|
|
246
|
+
let type = BUFFER_TYPE.ARRAY_BUFFER;
|
|
247
|
+
if (buffer.descriptor.usage & BufferUsage.INDEX) {
|
|
248
|
+
type = BUFFER_TYPE.ELEMENT_ARRAY_BUFFER;
|
|
249
|
+
} else if (buffer.descriptor.usage & BufferUsage.UNIFORM) {
|
|
250
|
+
type = BUFFER_TYPE.UNIFORM_BUFFER;
|
|
251
|
+
}
|
|
252
|
+
const glBuffer = new GlBuffer(gl.createBuffer(), type);
|
|
253
|
+
buffer._gpuData[this._renderer.uid] = glBuffer;
|
|
254
|
+
this._managedBuffers.add(buffer);
|
|
255
|
+
return glBuffer;
|
|
256
|
+
}
|
|
257
|
+
resetState() {
|
|
258
|
+
this._boundBufferBases = /* @__PURE__ */ Object.create(null);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
GlBufferSystem.extension = {
|
|
262
|
+
type: [
|
|
263
|
+
ExtensionType.WebGLSystem
|
|
264
|
+
],
|
|
265
|
+
name: "buffer"
|
|
266
|
+
};
|
|
267
|
+
const _GlContextSystem = class _GlContextSystem2 {
|
|
268
|
+
/** @param renderer - The renderer this System works for. */
|
|
269
|
+
constructor(renderer) {
|
|
270
|
+
this.supports = {
|
|
271
|
+
/** Support for 32-bit indices buffer. */
|
|
272
|
+
uint32Indices: true,
|
|
273
|
+
/** Support for UniformBufferObjects */
|
|
274
|
+
uniformBufferObject: true,
|
|
275
|
+
/** Support for VertexArrayObjects */
|
|
276
|
+
vertexArrayObject: true,
|
|
277
|
+
/** Support for SRGB texture format */
|
|
278
|
+
srgbTextures: true,
|
|
279
|
+
/** Support for wrapping modes if a texture is non-power of two */
|
|
280
|
+
nonPowOf2wrapping: true,
|
|
281
|
+
/** Support for MSAA (antialiasing of dynamic textures) */
|
|
282
|
+
msaa: true,
|
|
283
|
+
/** Support for mipmaps if a texture is non-power of two */
|
|
284
|
+
nonPowOf2mipmaps: true
|
|
285
|
+
};
|
|
286
|
+
this._renderer = renderer;
|
|
287
|
+
this.extensions = /* @__PURE__ */ Object.create(null);
|
|
288
|
+
this.handleContextLost = this.handleContextLost.bind(this);
|
|
289
|
+
this.handleContextRestored = this.handleContextRestored.bind(this);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* `true` if the context is lost
|
|
293
|
+
* @readonly
|
|
294
|
+
*/
|
|
295
|
+
get isLost() {
|
|
296
|
+
return !this.gl || this.gl.isContextLost();
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Handles the context change event.
|
|
300
|
+
* @param {WebGLRenderingContext} gl - New WebGL context.
|
|
301
|
+
*/
|
|
302
|
+
contextChange(gl) {
|
|
303
|
+
this.gl = gl;
|
|
304
|
+
this._renderer.gl = gl;
|
|
305
|
+
}
|
|
306
|
+
init(options) {
|
|
307
|
+
options = { ..._GlContextSystem2.defaultOptions, ...options };
|
|
308
|
+
let multiView = this.multiView = options.multiView;
|
|
309
|
+
if (options.context && multiView) {
|
|
310
|
+
warn("Renderer created with both a context and multiview enabled. Disabling multiView as both cannot work together.");
|
|
311
|
+
multiView = false;
|
|
312
|
+
}
|
|
313
|
+
if (multiView) {
|
|
314
|
+
this.canvas = DOMAdapter.get().createCanvas(this._renderer.canvas.width, this._renderer.canvas.height);
|
|
315
|
+
} else {
|
|
316
|
+
this.canvas = this._renderer.view.canvas;
|
|
317
|
+
}
|
|
318
|
+
if (options.context) {
|
|
319
|
+
this.initFromContext(options.context);
|
|
320
|
+
} else {
|
|
321
|
+
const alpha = this._renderer.background.alpha < 1;
|
|
322
|
+
const premultipliedAlpha = options.premultipliedAlpha ?? true;
|
|
323
|
+
const antialias = options.antialias && !this._renderer.backBuffer.useBackBuffer;
|
|
324
|
+
this.createContext(options.preferWebGLVersion, {
|
|
325
|
+
alpha,
|
|
326
|
+
premultipliedAlpha,
|
|
327
|
+
antialias,
|
|
328
|
+
stencil: true,
|
|
329
|
+
preserveDrawingBuffer: options.preserveDrawingBuffer,
|
|
330
|
+
powerPreference: options.powerPreference ?? "default"
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
ensureCanvasSize(targetCanvas) {
|
|
335
|
+
if (!this.multiView) {
|
|
336
|
+
if (targetCanvas !== this.canvas) {
|
|
337
|
+
warn("multiView is disabled, but targetCanvas is not the main canvas");
|
|
338
|
+
}
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const { canvas } = this;
|
|
342
|
+
if (canvas.width < targetCanvas.width || canvas.height < targetCanvas.height) {
|
|
343
|
+
canvas.width = Math.max(targetCanvas.width, targetCanvas.width);
|
|
344
|
+
canvas.height = Math.max(targetCanvas.height, targetCanvas.height);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Initializes the context.
|
|
349
|
+
* @protected
|
|
350
|
+
* @param {WebGLRenderingContext} gl - WebGL context
|
|
351
|
+
*/
|
|
352
|
+
initFromContext(gl) {
|
|
353
|
+
this.gl = gl;
|
|
354
|
+
this.webGLVersion = gl instanceof DOMAdapter.get().getWebGLRenderingContext() ? 1 : 2;
|
|
355
|
+
this.getExtensions();
|
|
356
|
+
this.validateContext(gl);
|
|
357
|
+
this._renderer.runners.contextChange.emit(gl);
|
|
358
|
+
const element = this._renderer.view.canvas;
|
|
359
|
+
element.addEventListener("webglcontextlost", this.handleContextLost, false);
|
|
360
|
+
element.addEventListener("webglcontextrestored", this.handleContextRestored, false);
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Initialize from context options
|
|
364
|
+
* @protected
|
|
365
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext
|
|
366
|
+
* @param preferWebGLVersion
|
|
367
|
+
* @param {object} options - context attributes
|
|
368
|
+
*/
|
|
369
|
+
createContext(preferWebGLVersion, options) {
|
|
370
|
+
let gl;
|
|
371
|
+
const canvas = this.canvas;
|
|
372
|
+
if (preferWebGLVersion === 2) {
|
|
373
|
+
gl = canvas.getContext("webgl2", options);
|
|
374
|
+
}
|
|
375
|
+
if (!gl) {
|
|
376
|
+
gl = canvas.getContext("webgl", options);
|
|
377
|
+
if (!gl) {
|
|
378
|
+
throw new Error("This browser does not support WebGL. Try using the canvas renderer");
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
this.gl = gl;
|
|
382
|
+
this.initFromContext(this.gl);
|
|
383
|
+
}
|
|
384
|
+
/** Auto-populate the {@link GlContextSystem.extensions extensions}. */
|
|
385
|
+
getExtensions() {
|
|
386
|
+
const { gl } = this;
|
|
387
|
+
const common = {
|
|
388
|
+
anisotropicFiltering: gl.getExtension("EXT_texture_filter_anisotropic"),
|
|
389
|
+
floatTextureLinear: gl.getExtension("OES_texture_float_linear"),
|
|
390
|
+
s3tc: gl.getExtension("WEBGL_compressed_texture_s3tc"),
|
|
391
|
+
s3tc_sRGB: gl.getExtension("WEBGL_compressed_texture_s3tc_srgb"),
|
|
392
|
+
// eslint-disable-line camelcase
|
|
393
|
+
etc: gl.getExtension("WEBGL_compressed_texture_etc"),
|
|
394
|
+
etc1: gl.getExtension("WEBGL_compressed_texture_etc1"),
|
|
395
|
+
pvrtc: gl.getExtension("WEBGL_compressed_texture_pvrtc") || gl.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc"),
|
|
396
|
+
atc: gl.getExtension("WEBGL_compressed_texture_atc"),
|
|
397
|
+
astc: gl.getExtension("WEBGL_compressed_texture_astc"),
|
|
398
|
+
bptc: gl.getExtension("EXT_texture_compression_bptc"),
|
|
399
|
+
rgtc: gl.getExtension("EXT_texture_compression_rgtc"),
|
|
400
|
+
loseContext: gl.getExtension("WEBGL_lose_context")
|
|
401
|
+
};
|
|
402
|
+
if (this.webGLVersion === 1) {
|
|
403
|
+
this.extensions = {
|
|
404
|
+
...common,
|
|
405
|
+
drawBuffers: gl.getExtension("WEBGL_draw_buffers"),
|
|
406
|
+
depthTexture: gl.getExtension("WEBGL_depth_texture"),
|
|
407
|
+
vertexArrayObject: gl.getExtension("OES_vertex_array_object") || gl.getExtension("MOZ_OES_vertex_array_object") || gl.getExtension("WEBKIT_OES_vertex_array_object"),
|
|
408
|
+
uint32ElementIndex: gl.getExtension("OES_element_index_uint"),
|
|
409
|
+
// Floats and half-floats
|
|
410
|
+
floatTexture: gl.getExtension("OES_texture_float"),
|
|
411
|
+
floatTextureLinear: gl.getExtension("OES_texture_float_linear"),
|
|
412
|
+
textureHalfFloat: gl.getExtension("OES_texture_half_float"),
|
|
413
|
+
textureHalfFloatLinear: gl.getExtension("OES_texture_half_float_linear"),
|
|
414
|
+
vertexAttribDivisorANGLE: gl.getExtension("ANGLE_instanced_arrays"),
|
|
415
|
+
srgb: gl.getExtension("EXT_sRGB")
|
|
416
|
+
};
|
|
417
|
+
} else {
|
|
418
|
+
this.extensions = {
|
|
419
|
+
...common,
|
|
420
|
+
colorBufferFloat: gl.getExtension("EXT_color_buffer_float")
|
|
421
|
+
};
|
|
422
|
+
const provokeExt = gl.getExtension("WEBGL_provoking_vertex");
|
|
423
|
+
if (provokeExt) {
|
|
424
|
+
provokeExt.provokingVertexWEBGL(provokeExt.FIRST_VERTEX_CONVENTION_WEBGL);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Handles a lost webgl context
|
|
430
|
+
* @param {WebGLContextEvent} event - The context lost event.
|
|
431
|
+
*/
|
|
432
|
+
handleContextLost(event) {
|
|
433
|
+
event.preventDefault();
|
|
434
|
+
if (this._contextLossForced) {
|
|
435
|
+
this._contextLossForced = false;
|
|
436
|
+
setTimeout(() => {
|
|
437
|
+
if (this.gl.isContextLost()) {
|
|
438
|
+
this.extensions.loseContext?.restoreContext();
|
|
439
|
+
}
|
|
440
|
+
}, 0);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
/** Handles a restored webgl context. */
|
|
444
|
+
handleContextRestored() {
|
|
445
|
+
this.getExtensions();
|
|
446
|
+
this._renderer.runners.contextChange.emit(this.gl);
|
|
447
|
+
}
|
|
448
|
+
destroy() {
|
|
449
|
+
const element = this._renderer.view.canvas;
|
|
450
|
+
this._renderer = null;
|
|
451
|
+
element.removeEventListener("webglcontextlost", this.handleContextLost);
|
|
452
|
+
element.removeEventListener("webglcontextrestored", this.handleContextRestored);
|
|
453
|
+
this.gl.useProgram(null);
|
|
454
|
+
this.extensions.loseContext?.loseContext();
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* this function can be called to force a webGL context loss
|
|
458
|
+
* this will release all resources on the GPU.
|
|
459
|
+
* Useful if you need to put Pixi to sleep, and save some GPU memory
|
|
460
|
+
*
|
|
461
|
+
* As soon as render is called - all resources will be created again.
|
|
462
|
+
*/
|
|
463
|
+
forceContextLoss() {
|
|
464
|
+
this.extensions.loseContext?.loseContext();
|
|
465
|
+
this._contextLossForced = true;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Validate context.
|
|
469
|
+
* @param {WebGLRenderingContext} gl - Render context.
|
|
470
|
+
*/
|
|
471
|
+
validateContext(gl) {
|
|
472
|
+
const attributes = gl.getContextAttributes();
|
|
473
|
+
if (attributes && !attributes.stencil) {
|
|
474
|
+
warn("Provided WebGL context does not have a stencil buffer, masks may not render correctly");
|
|
475
|
+
}
|
|
476
|
+
const supports = this.supports;
|
|
477
|
+
const isWebGl2 = this.webGLVersion === 2;
|
|
478
|
+
const extensions2 = this.extensions;
|
|
479
|
+
supports.uint32Indices = isWebGl2 || !!extensions2.uint32ElementIndex;
|
|
480
|
+
supports.uniformBufferObject = isWebGl2;
|
|
481
|
+
supports.vertexArrayObject = isWebGl2 || !!extensions2.vertexArrayObject;
|
|
482
|
+
supports.srgbTextures = isWebGl2 || !!extensions2.srgb;
|
|
483
|
+
supports.nonPowOf2wrapping = isWebGl2;
|
|
484
|
+
supports.nonPowOf2mipmaps = isWebGl2;
|
|
485
|
+
supports.msaa = isWebGl2;
|
|
486
|
+
if (!supports.uint32Indices) {
|
|
487
|
+
warn("Provided WebGL context does not support 32 index buffer, large scenes may not render correctly");
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
_GlContextSystem.extension = {
|
|
492
|
+
type: [
|
|
493
|
+
ExtensionType.WebGLSystem
|
|
494
|
+
],
|
|
495
|
+
name: "context"
|
|
496
|
+
};
|
|
497
|
+
_GlContextSystem.defaultOptions = {
|
|
498
|
+
/**
|
|
499
|
+
* {@link WebGLOptions.context}
|
|
500
|
+
* @default null
|
|
501
|
+
*/
|
|
502
|
+
context: null,
|
|
503
|
+
/**
|
|
504
|
+
* {@link WebGLOptions.premultipliedAlpha}
|
|
505
|
+
* @default true
|
|
506
|
+
*/
|
|
507
|
+
premultipliedAlpha: true,
|
|
508
|
+
/**
|
|
509
|
+
* {@link WebGLOptions.preserveDrawingBuffer}
|
|
510
|
+
* @default false
|
|
511
|
+
*/
|
|
512
|
+
preserveDrawingBuffer: false,
|
|
513
|
+
/**
|
|
514
|
+
* {@link WebGLOptions.powerPreference}
|
|
515
|
+
* @default default
|
|
516
|
+
*/
|
|
517
|
+
powerPreference: void 0,
|
|
518
|
+
/**
|
|
519
|
+
* {@link WebGLOptions.webGLVersion}
|
|
520
|
+
* @default 2
|
|
521
|
+
*/
|
|
522
|
+
preferWebGLVersion: 2,
|
|
523
|
+
/**
|
|
524
|
+
* {@link WebGLOptions.multiView}
|
|
525
|
+
* @default false
|
|
526
|
+
*/
|
|
527
|
+
multiView: false
|
|
528
|
+
};
|
|
529
|
+
let GlContextSystem = _GlContextSystem;
|
|
530
|
+
var GL_FORMATS = /* @__PURE__ */ ((GL_FORMATS2) => {
|
|
531
|
+
GL_FORMATS2[GL_FORMATS2["RGBA"] = 6408] = "RGBA";
|
|
532
|
+
GL_FORMATS2[GL_FORMATS2["RGB"] = 6407] = "RGB";
|
|
533
|
+
GL_FORMATS2[GL_FORMATS2["RG"] = 33319] = "RG";
|
|
534
|
+
GL_FORMATS2[GL_FORMATS2["RED"] = 6403] = "RED";
|
|
535
|
+
GL_FORMATS2[GL_FORMATS2["RGBA_INTEGER"] = 36249] = "RGBA_INTEGER";
|
|
536
|
+
GL_FORMATS2[GL_FORMATS2["RGB_INTEGER"] = 36248] = "RGB_INTEGER";
|
|
537
|
+
GL_FORMATS2[GL_FORMATS2["RG_INTEGER"] = 33320] = "RG_INTEGER";
|
|
538
|
+
GL_FORMATS2[GL_FORMATS2["RED_INTEGER"] = 36244] = "RED_INTEGER";
|
|
539
|
+
GL_FORMATS2[GL_FORMATS2["ALPHA"] = 6406] = "ALPHA";
|
|
540
|
+
GL_FORMATS2[GL_FORMATS2["LUMINANCE"] = 6409] = "LUMINANCE";
|
|
541
|
+
GL_FORMATS2[GL_FORMATS2["LUMINANCE_ALPHA"] = 6410] = "LUMINANCE_ALPHA";
|
|
542
|
+
GL_FORMATS2[GL_FORMATS2["DEPTH_COMPONENT"] = 6402] = "DEPTH_COMPONENT";
|
|
543
|
+
GL_FORMATS2[GL_FORMATS2["DEPTH_STENCIL"] = 34041] = "DEPTH_STENCIL";
|
|
544
|
+
return GL_FORMATS2;
|
|
545
|
+
})(GL_FORMATS || {});
|
|
546
|
+
var GL_TARGETS = /* @__PURE__ */ ((GL_TARGETS2) => {
|
|
547
|
+
GL_TARGETS2[GL_TARGETS2["TEXTURE_2D"] = 3553] = "TEXTURE_2D";
|
|
548
|
+
GL_TARGETS2[GL_TARGETS2["TEXTURE_CUBE_MAP"] = 34067] = "TEXTURE_CUBE_MAP";
|
|
549
|
+
GL_TARGETS2[GL_TARGETS2["TEXTURE_2D_ARRAY"] = 35866] = "TEXTURE_2D_ARRAY";
|
|
550
|
+
GL_TARGETS2[GL_TARGETS2["TEXTURE_CUBE_MAP_POSITIVE_X"] = 34069] = "TEXTURE_CUBE_MAP_POSITIVE_X";
|
|
551
|
+
GL_TARGETS2[GL_TARGETS2["TEXTURE_CUBE_MAP_NEGATIVE_X"] = 34070] = "TEXTURE_CUBE_MAP_NEGATIVE_X";
|
|
552
|
+
GL_TARGETS2[GL_TARGETS2["TEXTURE_CUBE_MAP_POSITIVE_Y"] = 34071] = "TEXTURE_CUBE_MAP_POSITIVE_Y";
|
|
553
|
+
GL_TARGETS2[GL_TARGETS2["TEXTURE_CUBE_MAP_NEGATIVE_Y"] = 34072] = "TEXTURE_CUBE_MAP_NEGATIVE_Y";
|
|
554
|
+
GL_TARGETS2[GL_TARGETS2["TEXTURE_CUBE_MAP_POSITIVE_Z"] = 34073] = "TEXTURE_CUBE_MAP_POSITIVE_Z";
|
|
555
|
+
GL_TARGETS2[GL_TARGETS2["TEXTURE_CUBE_MAP_NEGATIVE_Z"] = 34074] = "TEXTURE_CUBE_MAP_NEGATIVE_Z";
|
|
556
|
+
return GL_TARGETS2;
|
|
557
|
+
})(GL_TARGETS || {});
|
|
558
|
+
var GL_TYPES = /* @__PURE__ */ ((GL_TYPES2) => {
|
|
559
|
+
GL_TYPES2[GL_TYPES2["UNSIGNED_BYTE"] = 5121] = "UNSIGNED_BYTE";
|
|
560
|
+
GL_TYPES2[GL_TYPES2["UNSIGNED_SHORT"] = 5123] = "UNSIGNED_SHORT";
|
|
561
|
+
GL_TYPES2[GL_TYPES2["UNSIGNED_SHORT_5_6_5"] = 33635] = "UNSIGNED_SHORT_5_6_5";
|
|
562
|
+
GL_TYPES2[GL_TYPES2["UNSIGNED_SHORT_4_4_4_4"] = 32819] = "UNSIGNED_SHORT_4_4_4_4";
|
|
563
|
+
GL_TYPES2[GL_TYPES2["UNSIGNED_SHORT_5_5_5_1"] = 32820] = "UNSIGNED_SHORT_5_5_5_1";
|
|
564
|
+
GL_TYPES2[GL_TYPES2["UNSIGNED_INT"] = 5125] = "UNSIGNED_INT";
|
|
565
|
+
GL_TYPES2[GL_TYPES2["UNSIGNED_INT_10F_11F_11F_REV"] = 35899] = "UNSIGNED_INT_10F_11F_11F_REV";
|
|
566
|
+
GL_TYPES2[GL_TYPES2["UNSIGNED_INT_2_10_10_10_REV"] = 33640] = "UNSIGNED_INT_2_10_10_10_REV";
|
|
567
|
+
GL_TYPES2[GL_TYPES2["UNSIGNED_INT_24_8"] = 34042] = "UNSIGNED_INT_24_8";
|
|
568
|
+
GL_TYPES2[GL_TYPES2["UNSIGNED_INT_5_9_9_9_REV"] = 35902] = "UNSIGNED_INT_5_9_9_9_REV";
|
|
569
|
+
GL_TYPES2[GL_TYPES2["BYTE"] = 5120] = "BYTE";
|
|
570
|
+
GL_TYPES2[GL_TYPES2["SHORT"] = 5122] = "SHORT";
|
|
571
|
+
GL_TYPES2[GL_TYPES2["INT"] = 5124] = "INT";
|
|
572
|
+
GL_TYPES2[GL_TYPES2["FLOAT"] = 5126] = "FLOAT";
|
|
573
|
+
GL_TYPES2[GL_TYPES2["FLOAT_32_UNSIGNED_INT_24_8_REV"] = 36269] = "FLOAT_32_UNSIGNED_INT_24_8_REV";
|
|
574
|
+
GL_TYPES2[GL_TYPES2["HALF_FLOAT"] = 36193] = "HALF_FLOAT";
|
|
575
|
+
return GL_TYPES2;
|
|
576
|
+
})(GL_TYPES || {});
|
|
577
|
+
const infoMap = {
|
|
578
|
+
uint8x2: GL_TYPES.UNSIGNED_BYTE,
|
|
579
|
+
uint8x4: GL_TYPES.UNSIGNED_BYTE,
|
|
580
|
+
sint8x2: GL_TYPES.BYTE,
|
|
581
|
+
sint8x4: GL_TYPES.BYTE,
|
|
582
|
+
unorm8x2: GL_TYPES.UNSIGNED_BYTE,
|
|
583
|
+
unorm8x4: GL_TYPES.UNSIGNED_BYTE,
|
|
584
|
+
snorm8x2: GL_TYPES.BYTE,
|
|
585
|
+
snorm8x4: GL_TYPES.BYTE,
|
|
586
|
+
uint16x2: GL_TYPES.UNSIGNED_SHORT,
|
|
587
|
+
uint16x4: GL_TYPES.UNSIGNED_SHORT,
|
|
588
|
+
sint16x2: GL_TYPES.SHORT,
|
|
589
|
+
sint16x4: GL_TYPES.SHORT,
|
|
590
|
+
unorm16x2: GL_TYPES.UNSIGNED_SHORT,
|
|
591
|
+
unorm16x4: GL_TYPES.UNSIGNED_SHORT,
|
|
592
|
+
snorm16x2: GL_TYPES.SHORT,
|
|
593
|
+
snorm16x4: GL_TYPES.SHORT,
|
|
594
|
+
float16x2: GL_TYPES.HALF_FLOAT,
|
|
595
|
+
float16x4: GL_TYPES.HALF_FLOAT,
|
|
596
|
+
float32: GL_TYPES.FLOAT,
|
|
597
|
+
float32x2: GL_TYPES.FLOAT,
|
|
598
|
+
float32x3: GL_TYPES.FLOAT,
|
|
599
|
+
float32x4: GL_TYPES.FLOAT,
|
|
600
|
+
uint32: GL_TYPES.UNSIGNED_INT,
|
|
601
|
+
uint32x2: GL_TYPES.UNSIGNED_INT,
|
|
602
|
+
uint32x3: GL_TYPES.UNSIGNED_INT,
|
|
603
|
+
uint32x4: GL_TYPES.UNSIGNED_INT,
|
|
604
|
+
sint32: GL_TYPES.INT,
|
|
605
|
+
sint32x2: GL_TYPES.INT,
|
|
606
|
+
sint32x3: GL_TYPES.INT,
|
|
607
|
+
sint32x4: GL_TYPES.INT
|
|
608
|
+
};
|
|
609
|
+
function getGlTypeFromFormat(format) {
|
|
610
|
+
return infoMap[format] ?? infoMap.float32;
|
|
611
|
+
}
|
|
612
|
+
const topologyToGlMap = {
|
|
613
|
+
"point-list": 0,
|
|
614
|
+
"line-list": 1,
|
|
615
|
+
"line-strip": 3,
|
|
616
|
+
"triangle-list": 4,
|
|
617
|
+
"triangle-strip": 5
|
|
618
|
+
};
|
|
619
|
+
class GlGeometryGpuData {
|
|
620
|
+
constructor() {
|
|
621
|
+
this.vaoCache = /* @__PURE__ */ Object.create(null);
|
|
622
|
+
}
|
|
623
|
+
destroy() {
|
|
624
|
+
this.vaoCache = /* @__PURE__ */ Object.create(null);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
class GlGeometrySystem {
|
|
628
|
+
/** @param renderer - The renderer this System works for. */
|
|
629
|
+
constructor(renderer) {
|
|
630
|
+
this._renderer = renderer;
|
|
631
|
+
this._activeGeometry = null;
|
|
632
|
+
this._activeVao = null;
|
|
633
|
+
this.hasVao = true;
|
|
634
|
+
this.hasInstance = true;
|
|
635
|
+
this._managedGeometries = new GCManagedHash({
|
|
636
|
+
renderer,
|
|
637
|
+
type: "resource",
|
|
638
|
+
onUnload: this.onGeometryUnload.bind(this),
|
|
639
|
+
name: "glGeometry"
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
/** Sets up the renderer context and necessary buffers. */
|
|
643
|
+
contextChange() {
|
|
644
|
+
const gl = this.gl = this._renderer.gl;
|
|
645
|
+
if (!this._renderer.context.supports.vertexArrayObject) {
|
|
646
|
+
throw new Error("[PixiJS] Vertex Array Objects are not supported on this device");
|
|
647
|
+
}
|
|
648
|
+
this.destroyAll(true);
|
|
649
|
+
const nativeVaoExtension = this._renderer.context.extensions.vertexArrayObject;
|
|
650
|
+
if (nativeVaoExtension) {
|
|
651
|
+
gl.createVertexArray = () => nativeVaoExtension.createVertexArrayOES();
|
|
652
|
+
gl.bindVertexArray = (vao) => nativeVaoExtension.bindVertexArrayOES(vao);
|
|
653
|
+
gl.deleteVertexArray = (vao) => nativeVaoExtension.deleteVertexArrayOES(vao);
|
|
654
|
+
}
|
|
655
|
+
const nativeInstancedExtension = this._renderer.context.extensions.vertexAttribDivisorANGLE;
|
|
656
|
+
if (nativeInstancedExtension) {
|
|
657
|
+
gl.drawArraysInstanced = (a, b, c, d) => {
|
|
658
|
+
nativeInstancedExtension.drawArraysInstancedANGLE(a, b, c, d);
|
|
659
|
+
};
|
|
660
|
+
gl.drawElementsInstanced = (a, b, c, d, e) => {
|
|
661
|
+
nativeInstancedExtension.drawElementsInstancedANGLE(a, b, c, d, e);
|
|
662
|
+
};
|
|
663
|
+
gl.vertexAttribDivisor = (a, b) => nativeInstancedExtension.vertexAttribDivisorANGLE(a, b);
|
|
664
|
+
}
|
|
665
|
+
this._activeGeometry = null;
|
|
666
|
+
this._activeVao = null;
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Binds geometry so that is can be drawn. Creating a Vao if required
|
|
670
|
+
* @param geometry - Instance of geometry to bind.
|
|
671
|
+
* @param program - Instance of program to use vao for.
|
|
672
|
+
*/
|
|
673
|
+
bind(geometry, program) {
|
|
674
|
+
const gl = this.gl;
|
|
675
|
+
this._activeGeometry = geometry;
|
|
676
|
+
const vao = this.getVao(geometry, program);
|
|
677
|
+
if (this._activeVao !== vao) {
|
|
678
|
+
this._activeVao = vao;
|
|
679
|
+
gl.bindVertexArray(vao);
|
|
680
|
+
}
|
|
681
|
+
this.updateBuffers();
|
|
682
|
+
}
|
|
683
|
+
/** Reset and unbind any active VAO and geometry. */
|
|
684
|
+
resetState() {
|
|
685
|
+
this.unbind();
|
|
686
|
+
}
|
|
687
|
+
/** Update buffers of the currently bound geometry. */
|
|
688
|
+
updateBuffers() {
|
|
689
|
+
const geometry = this._activeGeometry;
|
|
690
|
+
const bufferSystem = this._renderer.buffer;
|
|
691
|
+
for (let i = 0; i < geometry.buffers.length; i++) {
|
|
692
|
+
const buffer = geometry.buffers[i];
|
|
693
|
+
bufferSystem.updateBuffer(buffer);
|
|
694
|
+
}
|
|
695
|
+
geometry._gcLastUsed = this._renderer.gc.now;
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Check compatibility between a geometry and a program
|
|
699
|
+
* @param geometry - Geometry instance.
|
|
700
|
+
* @param program - Program instance.
|
|
701
|
+
*/
|
|
702
|
+
checkCompatibility(geometry, program) {
|
|
703
|
+
const geometryAttributes = geometry.attributes;
|
|
704
|
+
const shaderAttributes = program._attributeData;
|
|
705
|
+
for (const j in shaderAttributes) {
|
|
706
|
+
if (!geometryAttributes[j]) {
|
|
707
|
+
throw new Error(`shader and geometry incompatible, geometry missing the "${j}" attribute`);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Takes a geometry and program and generates a unique signature for them.
|
|
713
|
+
* @param geometry - To get signature from.
|
|
714
|
+
* @param program - To test geometry against.
|
|
715
|
+
* @returns - Unique signature of the geometry and program
|
|
716
|
+
*/
|
|
717
|
+
getSignature(geometry, program) {
|
|
718
|
+
const attribs = geometry.attributes;
|
|
719
|
+
const shaderAttributes = program._attributeData;
|
|
720
|
+
const strings = ["g", geometry.uid];
|
|
721
|
+
for (const i in attribs) {
|
|
722
|
+
if (shaderAttributes[i]) {
|
|
723
|
+
strings.push(i, shaderAttributes[i].location);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
return strings.join("-");
|
|
727
|
+
}
|
|
728
|
+
getVao(geometry, program) {
|
|
729
|
+
return geometry._gpuData[this._renderer.uid]?.vaoCache[program._key] || this.initGeometryVao(geometry, program);
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Creates or gets Vao with the same structure as the geometry and stores it on the geometry.
|
|
733
|
+
* If vao is created, it is bound automatically. We use a shader to infer what and how to set up the
|
|
734
|
+
* attribute locations.
|
|
735
|
+
* @param geometry - Instance of geometry to to generate Vao for.
|
|
736
|
+
* @param program
|
|
737
|
+
* @param _incRefCount - Increment refCount of all geometry buffers.
|
|
738
|
+
*/
|
|
739
|
+
initGeometryVao(geometry, program, _incRefCount = true) {
|
|
740
|
+
const gl = this._renderer.gl;
|
|
741
|
+
const bufferSystem = this._renderer.buffer;
|
|
742
|
+
this._renderer.shader._getProgramData(program);
|
|
743
|
+
this.checkCompatibility(geometry, program);
|
|
744
|
+
const signature = this.getSignature(geometry, program);
|
|
745
|
+
let gpuData = geometry._gpuData[this._renderer.uid];
|
|
746
|
+
if (!gpuData) {
|
|
747
|
+
gpuData = new GlGeometryGpuData();
|
|
748
|
+
geometry._gpuData[this._renderer.uid] = gpuData;
|
|
749
|
+
this._managedGeometries.add(geometry);
|
|
750
|
+
}
|
|
751
|
+
const vaoObjectHash = gpuData.vaoCache;
|
|
752
|
+
let vao = vaoObjectHash[signature];
|
|
753
|
+
if (vao) {
|
|
754
|
+
vaoObjectHash[program._key] = vao;
|
|
755
|
+
return vao;
|
|
756
|
+
}
|
|
757
|
+
ensureAttributes(geometry, program._attributeData);
|
|
758
|
+
const buffers = geometry.buffers;
|
|
759
|
+
vao = gl.createVertexArray();
|
|
760
|
+
gl.bindVertexArray(vao);
|
|
761
|
+
for (let i = 0; i < buffers.length; i++) {
|
|
762
|
+
const buffer = buffers[i];
|
|
763
|
+
bufferSystem.bind(buffer);
|
|
764
|
+
}
|
|
765
|
+
this.activateVao(geometry, program);
|
|
766
|
+
vaoObjectHash[program._key] = vao;
|
|
767
|
+
vaoObjectHash[signature] = vao;
|
|
768
|
+
gl.bindVertexArray(null);
|
|
769
|
+
return vao;
|
|
770
|
+
}
|
|
771
|
+
onGeometryUnload(geometry, contextLost = false) {
|
|
772
|
+
const gpuData = geometry._gpuData[this._renderer.uid];
|
|
773
|
+
if (!gpuData) return;
|
|
774
|
+
const vaoCache = gpuData.vaoCache;
|
|
775
|
+
if (!contextLost) {
|
|
776
|
+
for (const i in vaoCache) {
|
|
777
|
+
if (this._activeVao !== vaoCache[i]) {
|
|
778
|
+
this.resetState();
|
|
779
|
+
}
|
|
780
|
+
this.gl.deleteVertexArray(vaoCache[i]);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Dispose all WebGL resources of all managed geometries.
|
|
786
|
+
* @param [contextLost=false] - If context was lost, we suppress `gl.delete` calls
|
|
787
|
+
*/
|
|
788
|
+
destroyAll(contextLost = false) {
|
|
789
|
+
this._managedGeometries.removeAll(contextLost);
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Activate vertex array object.
|
|
793
|
+
* @param geometry - Geometry instance.
|
|
794
|
+
* @param program - Shader program instance.
|
|
795
|
+
*/
|
|
796
|
+
activateVao(geometry, program) {
|
|
797
|
+
const gl = this._renderer.gl;
|
|
798
|
+
const bufferSystem = this._renderer.buffer;
|
|
799
|
+
const attributes = geometry.attributes;
|
|
800
|
+
if (geometry.indexBuffer) {
|
|
801
|
+
bufferSystem.bind(geometry.indexBuffer);
|
|
802
|
+
}
|
|
803
|
+
let lastBuffer = null;
|
|
804
|
+
for (const j in attributes) {
|
|
805
|
+
const attribute = attributes[j];
|
|
806
|
+
const buffer = attribute.buffer;
|
|
807
|
+
const glBuffer = bufferSystem.getGlBuffer(buffer);
|
|
808
|
+
const programAttrib = program._attributeData[j];
|
|
809
|
+
if (programAttrib) {
|
|
810
|
+
if (lastBuffer !== glBuffer) {
|
|
811
|
+
bufferSystem.bind(buffer);
|
|
812
|
+
lastBuffer = glBuffer;
|
|
813
|
+
}
|
|
814
|
+
const location = programAttrib.location;
|
|
815
|
+
gl.enableVertexAttribArray(location);
|
|
816
|
+
const attributeInfo = getAttributeInfoFromFormat(attribute.format);
|
|
817
|
+
const type = getGlTypeFromFormat(attribute.format);
|
|
818
|
+
if (programAttrib.format?.substring(1, 4) === "int") {
|
|
819
|
+
gl.vertexAttribIPointer(
|
|
820
|
+
location,
|
|
821
|
+
attributeInfo.size,
|
|
822
|
+
type,
|
|
823
|
+
attribute.stride,
|
|
824
|
+
attribute.offset
|
|
825
|
+
);
|
|
826
|
+
} else {
|
|
827
|
+
gl.vertexAttribPointer(
|
|
828
|
+
location,
|
|
829
|
+
attributeInfo.size,
|
|
830
|
+
type,
|
|
831
|
+
attributeInfo.normalised,
|
|
832
|
+
attribute.stride,
|
|
833
|
+
attribute.offset
|
|
834
|
+
);
|
|
835
|
+
}
|
|
836
|
+
if (attribute.instance) {
|
|
837
|
+
if (this.hasInstance) {
|
|
838
|
+
const divisor = attribute.divisor ?? 1;
|
|
839
|
+
gl.vertexAttribDivisor(location, divisor);
|
|
840
|
+
} else {
|
|
841
|
+
throw new Error("geometry error, GPU Instancing is not supported on this device");
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Draws the currently bound geometry.
|
|
849
|
+
* @param topology - The type primitive to render.
|
|
850
|
+
* @param size - The number of elements to be rendered. If not specified, all vertices after the
|
|
851
|
+
* starting vertex will be drawn.
|
|
852
|
+
* @param start - The starting vertex in the geometry to start drawing from. If not specified,
|
|
853
|
+
* drawing will start from the first vertex.
|
|
854
|
+
* @param instanceCount - The number of instances of the set of elements to execute. If not specified,
|
|
855
|
+
* all instances will be drawn.
|
|
856
|
+
* @returns This instance of the geometry system.
|
|
857
|
+
*/
|
|
858
|
+
draw(topology, size, start, instanceCount) {
|
|
859
|
+
const { gl } = this._renderer;
|
|
860
|
+
const geometry = this._activeGeometry;
|
|
861
|
+
const glTopology = topologyToGlMap[topology || geometry.topology];
|
|
862
|
+
instanceCount ?? (instanceCount = geometry.instanceCount);
|
|
863
|
+
if (geometry.indexBuffer) {
|
|
864
|
+
const byteSize = geometry.indexBuffer.data.BYTES_PER_ELEMENT;
|
|
865
|
+
const glType = byteSize === 2 ? gl.UNSIGNED_SHORT : gl.UNSIGNED_INT;
|
|
866
|
+
if (instanceCount !== 1) {
|
|
867
|
+
gl.drawElementsInstanced(glTopology, size || geometry.indexBuffer.data.length, glType, (start || 0) * byteSize, instanceCount);
|
|
868
|
+
} else {
|
|
869
|
+
gl.drawElements(glTopology, size || geometry.indexBuffer.data.length, glType, (start || 0) * byteSize);
|
|
870
|
+
}
|
|
871
|
+
} else if (instanceCount !== 1) {
|
|
872
|
+
gl.drawArraysInstanced(glTopology, start || 0, size || geometry.getSize(), instanceCount);
|
|
873
|
+
} else {
|
|
874
|
+
gl.drawArrays(glTopology, start || 0, size || geometry.getSize());
|
|
875
|
+
}
|
|
876
|
+
return this;
|
|
877
|
+
}
|
|
878
|
+
/** Unbind/reset everything. */
|
|
879
|
+
unbind() {
|
|
880
|
+
this.gl.bindVertexArray(null);
|
|
881
|
+
this._activeVao = null;
|
|
882
|
+
this._activeGeometry = null;
|
|
883
|
+
}
|
|
884
|
+
destroy() {
|
|
885
|
+
this._managedGeometries.destroy();
|
|
886
|
+
this._renderer = null;
|
|
887
|
+
this.gl = null;
|
|
888
|
+
this._activeVao = null;
|
|
889
|
+
this._activeGeometry = null;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
GlGeometrySystem.extension = {
|
|
893
|
+
type: [
|
|
894
|
+
ExtensionType.WebGLSystem
|
|
895
|
+
],
|
|
896
|
+
name: "geometry"
|
|
897
|
+
};
|
|
898
|
+
const bigTriangleGeometry = new Geometry({
|
|
899
|
+
attributes: {
|
|
900
|
+
aPosition: [
|
|
901
|
+
-1,
|
|
902
|
+
-1,
|
|
903
|
+
// Bottom left corner
|
|
904
|
+
3,
|
|
905
|
+
-1,
|
|
906
|
+
// Bottom right corner, extending beyond right edge
|
|
907
|
+
-1,
|
|
908
|
+
3
|
|
909
|
+
// Top left corner, extending beyond top edge
|
|
910
|
+
]
|
|
911
|
+
}
|
|
912
|
+
});
|
|
913
|
+
const _GlBackBufferSystem = class _GlBackBufferSystem2 {
|
|
914
|
+
constructor(renderer) {
|
|
915
|
+
this.useBackBuffer = false;
|
|
916
|
+
this._useBackBufferThisRender = false;
|
|
917
|
+
this._renderer = renderer;
|
|
918
|
+
}
|
|
919
|
+
init(options = {}) {
|
|
920
|
+
const { useBackBuffer, antialias } = { ..._GlBackBufferSystem2.defaultOptions, ...options };
|
|
921
|
+
this.useBackBuffer = useBackBuffer;
|
|
922
|
+
this._antialias = antialias;
|
|
923
|
+
if (!this._renderer.context.supports.msaa) {
|
|
924
|
+
warn("antialiasing, is not supported on when using the back buffer");
|
|
925
|
+
this._antialias = false;
|
|
926
|
+
}
|
|
927
|
+
this._state = State.for2d();
|
|
928
|
+
const bigTriangleProgram = new GlProgram({
|
|
929
|
+
vertex: `
|
|
930
|
+
attribute vec2 aPosition;
|
|
931
|
+
out vec2 vUv;
|
|
932
|
+
|
|
933
|
+
void main() {
|
|
934
|
+
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
935
|
+
|
|
936
|
+
vUv = (aPosition + 1.0) / 2.0;
|
|
937
|
+
|
|
938
|
+
// flip dem UVs
|
|
939
|
+
vUv.y = 1.0 - vUv.y;
|
|
940
|
+
}`,
|
|
941
|
+
fragment: `
|
|
942
|
+
in vec2 vUv;
|
|
943
|
+
out vec4 finalColor;
|
|
944
|
+
|
|
945
|
+
uniform sampler2D uTexture;
|
|
946
|
+
|
|
947
|
+
void main() {
|
|
948
|
+
finalColor = texture(uTexture, vUv);
|
|
949
|
+
}`,
|
|
950
|
+
name: "big-triangle"
|
|
951
|
+
});
|
|
952
|
+
this._bigTriangleShader = new Shader({
|
|
953
|
+
glProgram: bigTriangleProgram,
|
|
954
|
+
resources: {
|
|
955
|
+
uTexture: Texture.WHITE.source
|
|
956
|
+
}
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* This is called before the RenderTargetSystem is started. This is where
|
|
961
|
+
* we replace the target with the back buffer if required.
|
|
962
|
+
* @param options - The options for this render.
|
|
963
|
+
*/
|
|
964
|
+
renderStart(options) {
|
|
965
|
+
const renderTarget = this._renderer.renderTarget.getRenderTarget(options.target);
|
|
966
|
+
this._useBackBufferThisRender = this.useBackBuffer && !!renderTarget.isRoot;
|
|
967
|
+
if (this._useBackBufferThisRender) {
|
|
968
|
+
const renderTarget2 = this._renderer.renderTarget.getRenderTarget(options.target);
|
|
969
|
+
this._targetTexture = renderTarget2.colorTexture;
|
|
970
|
+
options.target = this._getBackBufferTexture(renderTarget2.colorTexture);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
renderEnd() {
|
|
974
|
+
this._presentBackBuffer();
|
|
975
|
+
}
|
|
976
|
+
_presentBackBuffer() {
|
|
977
|
+
const renderer = this._renderer;
|
|
978
|
+
renderer.renderTarget.finishRenderPass();
|
|
979
|
+
if (!this._useBackBufferThisRender) return;
|
|
980
|
+
renderer.renderTarget.bind(this._targetTexture, false);
|
|
981
|
+
this._bigTriangleShader.resources.uTexture = this._backBufferTexture.source;
|
|
982
|
+
renderer.encoder.draw({
|
|
983
|
+
geometry: bigTriangleGeometry,
|
|
984
|
+
shader: this._bigTriangleShader,
|
|
985
|
+
state: this._state
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
_getBackBufferTexture(targetSourceTexture) {
|
|
989
|
+
this._backBufferTexture = this._backBufferTexture || new Texture({
|
|
990
|
+
source: new TextureSource({
|
|
991
|
+
width: targetSourceTexture.width,
|
|
992
|
+
height: targetSourceTexture.height,
|
|
993
|
+
resolution: targetSourceTexture._resolution,
|
|
994
|
+
antialias: this._antialias
|
|
995
|
+
})
|
|
996
|
+
});
|
|
997
|
+
this._backBufferTexture.source.resize(
|
|
998
|
+
targetSourceTexture.width,
|
|
999
|
+
targetSourceTexture.height,
|
|
1000
|
+
targetSourceTexture._resolution
|
|
1001
|
+
);
|
|
1002
|
+
return this._backBufferTexture;
|
|
1003
|
+
}
|
|
1004
|
+
/** destroys the back buffer */
|
|
1005
|
+
destroy() {
|
|
1006
|
+
if (this._backBufferTexture) {
|
|
1007
|
+
this._backBufferTexture.destroy();
|
|
1008
|
+
this._backBufferTexture = null;
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
};
|
|
1012
|
+
_GlBackBufferSystem.extension = {
|
|
1013
|
+
type: [
|
|
1014
|
+
ExtensionType.WebGLSystem
|
|
1015
|
+
],
|
|
1016
|
+
name: "backBuffer",
|
|
1017
|
+
priority: 1
|
|
1018
|
+
};
|
|
1019
|
+
_GlBackBufferSystem.defaultOptions = {
|
|
1020
|
+
/** if true will use the back buffer where required */
|
|
1021
|
+
useBackBuffer: false
|
|
1022
|
+
};
|
|
1023
|
+
let GlBackBufferSystem = _GlBackBufferSystem;
|
|
1024
|
+
class GlColorMaskSystem {
|
|
1025
|
+
constructor(renderer) {
|
|
1026
|
+
this._colorMaskCache = 15;
|
|
1027
|
+
this._renderer = renderer;
|
|
1028
|
+
}
|
|
1029
|
+
setMask(colorMask) {
|
|
1030
|
+
if (this._colorMaskCache === colorMask) return;
|
|
1031
|
+
this._colorMaskCache = colorMask;
|
|
1032
|
+
this._renderer.gl.colorMask(
|
|
1033
|
+
!!(colorMask & 8),
|
|
1034
|
+
!!(colorMask & 4),
|
|
1035
|
+
!!(colorMask & 2),
|
|
1036
|
+
!!(colorMask & 1)
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
GlColorMaskSystem.extension = {
|
|
1041
|
+
type: [
|
|
1042
|
+
ExtensionType.WebGLSystem
|
|
1043
|
+
],
|
|
1044
|
+
name: "colorMask"
|
|
1045
|
+
};
|
|
1046
|
+
class GlEncoderSystem {
|
|
1047
|
+
constructor(renderer) {
|
|
1048
|
+
this.commandFinished = Promise.resolve();
|
|
1049
|
+
this._renderer = renderer;
|
|
1050
|
+
}
|
|
1051
|
+
setGeometry(geometry, shader) {
|
|
1052
|
+
this._renderer.geometry.bind(geometry, shader.glProgram);
|
|
1053
|
+
}
|
|
1054
|
+
finishRenderPass() {
|
|
1055
|
+
}
|
|
1056
|
+
draw(options) {
|
|
1057
|
+
const renderer = this._renderer;
|
|
1058
|
+
const { geometry, shader, state, skipSync, topology: type, size, start, instanceCount } = options;
|
|
1059
|
+
renderer.shader.bind(shader, skipSync);
|
|
1060
|
+
renderer.geometry.bind(geometry, renderer.shader._activeProgram);
|
|
1061
|
+
if (state) {
|
|
1062
|
+
renderer.state.set(state);
|
|
1063
|
+
}
|
|
1064
|
+
renderer.geometry.draw(type, size, start, instanceCount ?? geometry.instanceCount);
|
|
1065
|
+
}
|
|
1066
|
+
destroy() {
|
|
1067
|
+
this._renderer = null;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
GlEncoderSystem.extension = {
|
|
1071
|
+
type: [
|
|
1072
|
+
ExtensionType.WebGLSystem
|
|
1073
|
+
],
|
|
1074
|
+
name: "encoder"
|
|
1075
|
+
};
|
|
1076
|
+
class GlLimitsSystem {
|
|
1077
|
+
constructor(renderer) {
|
|
1078
|
+
this._renderer = renderer;
|
|
1079
|
+
}
|
|
1080
|
+
contextChange() {
|
|
1081
|
+
const gl = this._renderer.gl;
|
|
1082
|
+
this.maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
|
|
1083
|
+
this.maxBatchableTextures = checkMaxIfStatementsInShader(this.maxTextures, gl);
|
|
1084
|
+
const isWebGl2 = this._renderer.context.webGLVersion === 2;
|
|
1085
|
+
this.maxUniformBindings = isWebGl2 ? gl.getParameter(gl.MAX_UNIFORM_BUFFER_BINDINGS) : 0;
|
|
1086
|
+
}
|
|
1087
|
+
destroy() {
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
GlLimitsSystem.extension = {
|
|
1091
|
+
type: [
|
|
1092
|
+
ExtensionType.WebGLSystem
|
|
1093
|
+
],
|
|
1094
|
+
name: "limits"
|
|
1095
|
+
};
|
|
1096
|
+
class GlRenderTarget {
|
|
1097
|
+
constructor() {
|
|
1098
|
+
this.width = -1;
|
|
1099
|
+
this.height = -1;
|
|
1100
|
+
this.msaa = false;
|
|
1101
|
+
this._attachedMipLevel = 0;
|
|
1102
|
+
this._attachedLayer = 0;
|
|
1103
|
+
this.msaaRenderBuffer = [];
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
class GlStencilSystem {
|
|
1107
|
+
constructor(renderer) {
|
|
1108
|
+
this._stencilCache = {
|
|
1109
|
+
enabled: false,
|
|
1110
|
+
stencilReference: 0,
|
|
1111
|
+
stencilMode: STENCIL_MODES.NONE
|
|
1112
|
+
};
|
|
1113
|
+
this._renderTargetStencilState = /* @__PURE__ */ Object.create(null);
|
|
1114
|
+
renderer.renderTarget.onRenderTargetChange.add(this);
|
|
1115
|
+
}
|
|
1116
|
+
contextChange(gl) {
|
|
1117
|
+
this._gl = gl;
|
|
1118
|
+
this._comparisonFuncMapping = {
|
|
1119
|
+
always: gl.ALWAYS,
|
|
1120
|
+
never: gl.NEVER,
|
|
1121
|
+
equal: gl.EQUAL,
|
|
1122
|
+
"not-equal": gl.NOTEQUAL,
|
|
1123
|
+
less: gl.LESS,
|
|
1124
|
+
"less-equal": gl.LEQUAL,
|
|
1125
|
+
greater: gl.GREATER,
|
|
1126
|
+
"greater-equal": gl.GEQUAL
|
|
1127
|
+
};
|
|
1128
|
+
this._stencilOpsMapping = {
|
|
1129
|
+
keep: gl.KEEP,
|
|
1130
|
+
zero: gl.ZERO,
|
|
1131
|
+
replace: gl.REPLACE,
|
|
1132
|
+
invert: gl.INVERT,
|
|
1133
|
+
"increment-clamp": gl.INCR,
|
|
1134
|
+
"decrement-clamp": gl.DECR,
|
|
1135
|
+
"increment-wrap": gl.INCR_WRAP,
|
|
1136
|
+
"decrement-wrap": gl.DECR_WRAP
|
|
1137
|
+
};
|
|
1138
|
+
this.resetState();
|
|
1139
|
+
}
|
|
1140
|
+
onRenderTargetChange(renderTarget) {
|
|
1141
|
+
if (this._activeRenderTarget === renderTarget) return;
|
|
1142
|
+
this._activeRenderTarget = renderTarget;
|
|
1143
|
+
let stencilState = this._renderTargetStencilState[renderTarget.uid];
|
|
1144
|
+
if (!stencilState) {
|
|
1145
|
+
stencilState = this._renderTargetStencilState[renderTarget.uid] = {
|
|
1146
|
+
stencilMode: STENCIL_MODES.DISABLED,
|
|
1147
|
+
stencilReference: 0
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
this.setStencilMode(stencilState.stencilMode, stencilState.stencilReference);
|
|
1151
|
+
}
|
|
1152
|
+
resetState() {
|
|
1153
|
+
this._stencilCache.enabled = false;
|
|
1154
|
+
this._stencilCache.stencilMode = STENCIL_MODES.NONE;
|
|
1155
|
+
this._stencilCache.stencilReference = 0;
|
|
1156
|
+
}
|
|
1157
|
+
setStencilMode(stencilMode, stencilReference) {
|
|
1158
|
+
const stencilState = this._renderTargetStencilState[this._activeRenderTarget.uid];
|
|
1159
|
+
const gl = this._gl;
|
|
1160
|
+
const mode = GpuStencilModesToPixi[stencilMode];
|
|
1161
|
+
const _stencilCache = this._stencilCache;
|
|
1162
|
+
stencilState.stencilMode = stencilMode;
|
|
1163
|
+
stencilState.stencilReference = stencilReference;
|
|
1164
|
+
if (stencilMode === STENCIL_MODES.DISABLED) {
|
|
1165
|
+
if (this._stencilCache.enabled) {
|
|
1166
|
+
this._stencilCache.enabled = false;
|
|
1167
|
+
gl.disable(gl.STENCIL_TEST);
|
|
1168
|
+
}
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
if (!this._stencilCache.enabled) {
|
|
1172
|
+
this._stencilCache.enabled = true;
|
|
1173
|
+
gl.enable(gl.STENCIL_TEST);
|
|
1174
|
+
}
|
|
1175
|
+
if (stencilMode !== _stencilCache.stencilMode || _stencilCache.stencilReference !== stencilReference) {
|
|
1176
|
+
_stencilCache.stencilMode = stencilMode;
|
|
1177
|
+
_stencilCache.stencilReference = stencilReference;
|
|
1178
|
+
gl.stencilFunc(this._comparisonFuncMapping[mode.stencilBack.compare], stencilReference, 255);
|
|
1179
|
+
gl.stencilOp(gl.KEEP, gl.KEEP, this._stencilOpsMapping[mode.stencilBack.passOp]);
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
GlStencilSystem.extension = {
|
|
1184
|
+
type: [
|
|
1185
|
+
ExtensionType.WebGLSystem
|
|
1186
|
+
],
|
|
1187
|
+
name: "stencil"
|
|
1188
|
+
};
|
|
1189
|
+
const WGSL_TO_STD40_SIZE = {
|
|
1190
|
+
f32: 4,
|
|
1191
|
+
i32: 4,
|
|
1192
|
+
"vec2<f32>": 8,
|
|
1193
|
+
"vec3<f32>": 12,
|
|
1194
|
+
"vec4<f32>": 16,
|
|
1195
|
+
"vec2<i32>": 8,
|
|
1196
|
+
"vec3<i32>": 12,
|
|
1197
|
+
"vec4<i32>": 16,
|
|
1198
|
+
"mat2x2<f32>": 16 * 2,
|
|
1199
|
+
"mat3x3<f32>": 16 * 3,
|
|
1200
|
+
"mat4x4<f32>": 16 * 4
|
|
1201
|
+
// TODO - not essential for now but support these in the future
|
|
1202
|
+
// int: 4,
|
|
1203
|
+
// ivec2: 8,
|
|
1204
|
+
// ivec3: 12,
|
|
1205
|
+
// ivec4: 16,
|
|
1206
|
+
// uint: 4,
|
|
1207
|
+
// uvec2: 8,
|
|
1208
|
+
// uvec3: 12,
|
|
1209
|
+
// uvec4: 16,
|
|
1210
|
+
// bool: 4,
|
|
1211
|
+
// bvec2: 8,
|
|
1212
|
+
// bvec3: 12,
|
|
1213
|
+
// bvec4: 16,
|
|
1214
|
+
// mat2: 16 * 2,
|
|
1215
|
+
// mat3: 16 * 3,
|
|
1216
|
+
// mat4: 16 * 4,
|
|
1217
|
+
};
|
|
1218
|
+
function createUboElementsSTD40(uniformData) {
|
|
1219
|
+
const uboElements = uniformData.map((data) => ({
|
|
1220
|
+
data,
|
|
1221
|
+
offset: 0,
|
|
1222
|
+
size: 0
|
|
1223
|
+
}));
|
|
1224
|
+
const chunkSize = 16;
|
|
1225
|
+
let size = 0;
|
|
1226
|
+
let offset = 0;
|
|
1227
|
+
for (let i = 0; i < uboElements.length; i++) {
|
|
1228
|
+
const uboElement = uboElements[i];
|
|
1229
|
+
size = WGSL_TO_STD40_SIZE[uboElement.data.type];
|
|
1230
|
+
if (!size) {
|
|
1231
|
+
throw new Error(`Unknown type ${uboElement.data.type}`);
|
|
1232
|
+
}
|
|
1233
|
+
if (uboElement.data.size > 1) {
|
|
1234
|
+
size = Math.max(size, chunkSize) * uboElement.data.size;
|
|
1235
|
+
}
|
|
1236
|
+
const boundary = size === 12 ? 16 : size;
|
|
1237
|
+
uboElement.size = size;
|
|
1238
|
+
const curOffset = offset % chunkSize;
|
|
1239
|
+
if (curOffset > 0 && chunkSize - curOffset < boundary) {
|
|
1240
|
+
offset += (chunkSize - curOffset) % 16;
|
|
1241
|
+
} else {
|
|
1242
|
+
offset += (size - curOffset % size) % size;
|
|
1243
|
+
}
|
|
1244
|
+
uboElement.offset = offset;
|
|
1245
|
+
offset += size;
|
|
1246
|
+
}
|
|
1247
|
+
offset = Math.ceil(offset / 16) * 16;
|
|
1248
|
+
return { uboElements, size: offset };
|
|
1249
|
+
}
|
|
1250
|
+
function generateArraySyncSTD40(uboElement, offsetToAdd) {
|
|
1251
|
+
const rowSize = Math.max(WGSL_TO_STD40_SIZE[uboElement.data.type] / 16, 1);
|
|
1252
|
+
const elementSize = uboElement.data.value.length / uboElement.data.size;
|
|
1253
|
+
const remainder = (4 - elementSize % 4) % 4;
|
|
1254
|
+
const data = uboElement.data.type.indexOf("i32") >= 0 ? "dataInt32" : "data";
|
|
1255
|
+
return `
|
|
1256
|
+
v = uv.${uboElement.data.name};
|
|
1257
|
+
offset += ${offsetToAdd};
|
|
1258
|
+
|
|
1259
|
+
arrayOffset = offset;
|
|
1260
|
+
|
|
1261
|
+
t = 0;
|
|
1262
|
+
|
|
1263
|
+
for(var i=0; i < ${uboElement.data.size * rowSize}; i++)
|
|
1264
|
+
{
|
|
1265
|
+
for(var j = 0; j < ${elementSize}; j++)
|
|
1266
|
+
{
|
|
1267
|
+
${data}[arrayOffset++] = v[t++];
|
|
1268
|
+
}
|
|
1269
|
+
${remainder !== 0 ? `arrayOffset += ${remainder};` : ""}
|
|
1270
|
+
}
|
|
1271
|
+
`;
|
|
1272
|
+
}
|
|
1273
|
+
function createUboSyncFunctionSTD40(uboElements) {
|
|
1274
|
+
return createUboSyncFunction(
|
|
1275
|
+
uboElements,
|
|
1276
|
+
"uboStd40",
|
|
1277
|
+
generateArraySyncSTD40,
|
|
1278
|
+
uboSyncFunctionsSTD40
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
class GlUboSystem extends UboSystem {
|
|
1282
|
+
constructor() {
|
|
1283
|
+
super({
|
|
1284
|
+
createUboElements: createUboElementsSTD40,
|
|
1285
|
+
generateUboSync: createUboSyncFunctionSTD40
|
|
1286
|
+
});
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
GlUboSystem.extension = {
|
|
1290
|
+
type: [ExtensionType.WebGLSystem],
|
|
1291
|
+
name: "ubo"
|
|
1292
|
+
};
|
|
1293
|
+
class GlRenderTargetAdaptor {
|
|
1294
|
+
constructor() {
|
|
1295
|
+
this._clearColorCache = [0, 0, 0, 0];
|
|
1296
|
+
this._viewPortCache = new Rectangle();
|
|
1297
|
+
}
|
|
1298
|
+
init(renderer, renderTargetSystem) {
|
|
1299
|
+
this._renderer = renderer;
|
|
1300
|
+
this._renderTargetSystem = renderTargetSystem;
|
|
1301
|
+
renderer.runners.contextChange.add(this);
|
|
1302
|
+
}
|
|
1303
|
+
contextChange() {
|
|
1304
|
+
this._clearColorCache = [0, 0, 0, 0];
|
|
1305
|
+
this._viewPortCache = new Rectangle();
|
|
1306
|
+
const gl = this._renderer.gl;
|
|
1307
|
+
this._drawBuffersCache = [];
|
|
1308
|
+
for (let i = 1; i <= 16; i++) {
|
|
1309
|
+
this._drawBuffersCache[i] = Array.from({ length: i }, (_, j) => gl.COLOR_ATTACHMENT0 + j);
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
copyToTexture(sourceRenderSurfaceTexture, destinationTexture, originSrc, size, originDest) {
|
|
1313
|
+
const renderTargetSystem = this._renderTargetSystem;
|
|
1314
|
+
const renderer = this._renderer;
|
|
1315
|
+
const glRenderTarget = renderTargetSystem.getGpuRenderTarget(sourceRenderSurfaceTexture);
|
|
1316
|
+
const gl = renderer.gl;
|
|
1317
|
+
this.finishRenderPass(sourceRenderSurfaceTexture);
|
|
1318
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, glRenderTarget.resolveTargetFramebuffer);
|
|
1319
|
+
renderer.texture.bind(destinationTexture, 0);
|
|
1320
|
+
gl.copyTexSubImage2D(
|
|
1321
|
+
gl.TEXTURE_2D,
|
|
1322
|
+
0,
|
|
1323
|
+
originDest.x,
|
|
1324
|
+
originDest.y,
|
|
1325
|
+
originSrc.x,
|
|
1326
|
+
originSrc.y,
|
|
1327
|
+
size.width,
|
|
1328
|
+
size.height
|
|
1329
|
+
);
|
|
1330
|
+
return destinationTexture;
|
|
1331
|
+
}
|
|
1332
|
+
startRenderPass(renderTarget, clear = true, clearColor, viewport, mipLevel = 0, layer = 0) {
|
|
1333
|
+
const renderTargetSystem = this._renderTargetSystem;
|
|
1334
|
+
const source = renderTarget.colorTexture;
|
|
1335
|
+
const gpuRenderTarget = renderTargetSystem.getGpuRenderTarget(renderTarget);
|
|
1336
|
+
if (layer !== 0 && this._renderer.context.webGLVersion < 2) {
|
|
1337
|
+
throw new Error("[RenderTargetSystem] Rendering to array layers requires WebGL2.");
|
|
1338
|
+
}
|
|
1339
|
+
if (mipLevel > 0) {
|
|
1340
|
+
if (gpuRenderTarget.msaa) {
|
|
1341
|
+
throw new Error("[RenderTargetSystem] Rendering to mip levels is not supported with MSAA render targets.");
|
|
1342
|
+
}
|
|
1343
|
+
if (this._renderer.context.webGLVersion < 2) {
|
|
1344
|
+
throw new Error("[RenderTargetSystem] Rendering to mip levels requires WebGL2.");
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
let viewPortY = viewport.y;
|
|
1348
|
+
if (renderTarget.isRoot) {
|
|
1349
|
+
viewPortY = source.pixelHeight - viewport.height - viewport.y;
|
|
1350
|
+
}
|
|
1351
|
+
renderTarget.colorTextures.forEach((texture) => {
|
|
1352
|
+
this._renderer.texture.unbind(texture);
|
|
1353
|
+
});
|
|
1354
|
+
const gl = this._renderer.gl;
|
|
1355
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, gpuRenderTarget.framebuffer);
|
|
1356
|
+
if (!renderTarget.isRoot && (gpuRenderTarget._attachedMipLevel !== mipLevel || gpuRenderTarget._attachedLayer !== layer)) {
|
|
1357
|
+
renderTarget.colorTextures.forEach((colorTexture, i) => {
|
|
1358
|
+
const glSource = this._renderer.texture.getGlSource(colorTexture);
|
|
1359
|
+
if (glSource.target === gl.TEXTURE_2D) {
|
|
1360
|
+
if (layer !== 0) {
|
|
1361
|
+
throw new Error("[RenderTargetSystem] layer must be 0 when rendering to 2D textures in WebGL.");
|
|
1362
|
+
}
|
|
1363
|
+
gl.framebufferTexture2D(
|
|
1364
|
+
gl.FRAMEBUFFER,
|
|
1365
|
+
gl.COLOR_ATTACHMENT0 + i,
|
|
1366
|
+
gl.TEXTURE_2D,
|
|
1367
|
+
glSource.texture,
|
|
1368
|
+
mipLevel
|
|
1369
|
+
);
|
|
1370
|
+
} else if (glSource.target === gl.TEXTURE_2D_ARRAY) {
|
|
1371
|
+
if (this._renderer.context.webGLVersion < 2) {
|
|
1372
|
+
throw new Error("[RenderTargetSystem] Rendering to 2D array textures requires WebGL2.");
|
|
1373
|
+
}
|
|
1374
|
+
gl.framebufferTextureLayer(
|
|
1375
|
+
gl.FRAMEBUFFER,
|
|
1376
|
+
gl.COLOR_ATTACHMENT0 + i,
|
|
1377
|
+
glSource.texture,
|
|
1378
|
+
mipLevel,
|
|
1379
|
+
layer
|
|
1380
|
+
);
|
|
1381
|
+
} else if (glSource.target === gl.TEXTURE_CUBE_MAP) {
|
|
1382
|
+
if (layer < 0 || layer > 5) {
|
|
1383
|
+
throw new Error("[RenderTargetSystem] Cube map layer must be between 0 and 5.");
|
|
1384
|
+
}
|
|
1385
|
+
gl.framebufferTexture2D(
|
|
1386
|
+
gl.FRAMEBUFFER,
|
|
1387
|
+
gl.COLOR_ATTACHMENT0 + i,
|
|
1388
|
+
gl.TEXTURE_CUBE_MAP_POSITIVE_X + layer,
|
|
1389
|
+
glSource.texture,
|
|
1390
|
+
mipLevel
|
|
1391
|
+
);
|
|
1392
|
+
} else {
|
|
1393
|
+
throw new Error("[RenderTargetSystem] Unsupported texture target for render-to-layer in WebGL.");
|
|
1394
|
+
}
|
|
1395
|
+
});
|
|
1396
|
+
gpuRenderTarget._attachedMipLevel = mipLevel;
|
|
1397
|
+
gpuRenderTarget._attachedLayer = layer;
|
|
1398
|
+
}
|
|
1399
|
+
if (renderTarget.colorTextures.length > 1) {
|
|
1400
|
+
this._setDrawBuffers(renderTarget, gl);
|
|
1401
|
+
}
|
|
1402
|
+
const viewPortCache = this._viewPortCache;
|
|
1403
|
+
if (viewPortCache.x !== viewport.x || viewPortCache.y !== viewPortY || viewPortCache.width !== viewport.width || viewPortCache.height !== viewport.height) {
|
|
1404
|
+
viewPortCache.x = viewport.x;
|
|
1405
|
+
viewPortCache.y = viewPortY;
|
|
1406
|
+
viewPortCache.width = viewport.width;
|
|
1407
|
+
viewPortCache.height = viewport.height;
|
|
1408
|
+
gl.viewport(
|
|
1409
|
+
viewport.x,
|
|
1410
|
+
viewPortY,
|
|
1411
|
+
viewport.width,
|
|
1412
|
+
viewport.height
|
|
1413
|
+
);
|
|
1414
|
+
}
|
|
1415
|
+
if (!gpuRenderTarget.depthStencilRenderBuffer && (renderTarget.stencil || renderTarget.depth)) {
|
|
1416
|
+
this._initStencil(gpuRenderTarget);
|
|
1417
|
+
}
|
|
1418
|
+
this.clear(renderTarget, clear, clearColor);
|
|
1419
|
+
}
|
|
1420
|
+
finishRenderPass(renderTarget) {
|
|
1421
|
+
const renderTargetSystem = this._renderTargetSystem;
|
|
1422
|
+
const glRenderTarget = renderTargetSystem.getGpuRenderTarget(renderTarget);
|
|
1423
|
+
if (!glRenderTarget.msaa) return;
|
|
1424
|
+
const gl = this._renderer.gl;
|
|
1425
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, glRenderTarget.resolveTargetFramebuffer);
|
|
1426
|
+
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, glRenderTarget.framebuffer);
|
|
1427
|
+
gl.blitFramebuffer(
|
|
1428
|
+
0,
|
|
1429
|
+
0,
|
|
1430
|
+
glRenderTarget.width,
|
|
1431
|
+
glRenderTarget.height,
|
|
1432
|
+
0,
|
|
1433
|
+
0,
|
|
1434
|
+
glRenderTarget.width,
|
|
1435
|
+
glRenderTarget.height,
|
|
1436
|
+
gl.COLOR_BUFFER_BIT,
|
|
1437
|
+
gl.NEAREST
|
|
1438
|
+
);
|
|
1439
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, glRenderTarget.framebuffer);
|
|
1440
|
+
}
|
|
1441
|
+
initGpuRenderTarget(renderTarget) {
|
|
1442
|
+
const renderer = this._renderer;
|
|
1443
|
+
const gl = renderer.gl;
|
|
1444
|
+
const glRenderTarget = new GlRenderTarget();
|
|
1445
|
+
glRenderTarget._attachedMipLevel = 0;
|
|
1446
|
+
glRenderTarget._attachedLayer = 0;
|
|
1447
|
+
const colorTexture = renderTarget.colorTexture;
|
|
1448
|
+
if (colorTexture instanceof CanvasSource) {
|
|
1449
|
+
this._renderer.context.ensureCanvasSize(renderTarget.colorTexture.resource);
|
|
1450
|
+
glRenderTarget.framebuffer = null;
|
|
1451
|
+
return glRenderTarget;
|
|
1452
|
+
}
|
|
1453
|
+
this._initColor(renderTarget, glRenderTarget);
|
|
1454
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
1455
|
+
return glRenderTarget;
|
|
1456
|
+
}
|
|
1457
|
+
destroyGpuRenderTarget(gpuRenderTarget) {
|
|
1458
|
+
const gl = this._renderer.gl;
|
|
1459
|
+
if (gpuRenderTarget.framebuffer) {
|
|
1460
|
+
gl.deleteFramebuffer(gpuRenderTarget.framebuffer);
|
|
1461
|
+
gpuRenderTarget.framebuffer = null;
|
|
1462
|
+
}
|
|
1463
|
+
if (gpuRenderTarget.resolveTargetFramebuffer) {
|
|
1464
|
+
gl.deleteFramebuffer(gpuRenderTarget.resolveTargetFramebuffer);
|
|
1465
|
+
gpuRenderTarget.resolveTargetFramebuffer = null;
|
|
1466
|
+
}
|
|
1467
|
+
if (gpuRenderTarget.depthStencilRenderBuffer) {
|
|
1468
|
+
gl.deleteRenderbuffer(gpuRenderTarget.depthStencilRenderBuffer);
|
|
1469
|
+
gpuRenderTarget.depthStencilRenderBuffer = null;
|
|
1470
|
+
}
|
|
1471
|
+
gpuRenderTarget.msaaRenderBuffer.forEach((renderBuffer) => {
|
|
1472
|
+
gl.deleteRenderbuffer(renderBuffer);
|
|
1473
|
+
});
|
|
1474
|
+
gpuRenderTarget.msaaRenderBuffer = null;
|
|
1475
|
+
}
|
|
1476
|
+
clear(_renderTarget, clear, clearColor, _viewport, _mipLevel = 0, layer = 0) {
|
|
1477
|
+
if (!clear) return;
|
|
1478
|
+
if (layer !== 0) {
|
|
1479
|
+
throw new Error("[RenderTargetSystem] Clearing array layers is not supported in WebGL renderer.");
|
|
1480
|
+
}
|
|
1481
|
+
const renderTargetSystem = this._renderTargetSystem;
|
|
1482
|
+
if (typeof clear === "boolean") {
|
|
1483
|
+
clear = clear ? CLEAR.ALL : CLEAR.NONE;
|
|
1484
|
+
}
|
|
1485
|
+
const gl = this._renderer.gl;
|
|
1486
|
+
if (clear & CLEAR.COLOR) {
|
|
1487
|
+
clearColor ?? (clearColor = renderTargetSystem.defaultClearColor);
|
|
1488
|
+
const clearColorCache = this._clearColorCache;
|
|
1489
|
+
const clearColorArray = clearColor;
|
|
1490
|
+
if (clearColorCache[0] !== clearColorArray[0] || clearColorCache[1] !== clearColorArray[1] || clearColorCache[2] !== clearColorArray[2] || clearColorCache[3] !== clearColorArray[3]) {
|
|
1491
|
+
clearColorCache[0] = clearColorArray[0];
|
|
1492
|
+
clearColorCache[1] = clearColorArray[1];
|
|
1493
|
+
clearColorCache[2] = clearColorArray[2];
|
|
1494
|
+
clearColorCache[3] = clearColorArray[3];
|
|
1495
|
+
gl.clearColor(clearColorArray[0], clearColorArray[1], clearColorArray[2], clearColorArray[3]);
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
gl.clear(clear);
|
|
1499
|
+
}
|
|
1500
|
+
resizeGpuRenderTarget(renderTarget) {
|
|
1501
|
+
if (renderTarget.isRoot) return;
|
|
1502
|
+
const renderTargetSystem = this._renderTargetSystem;
|
|
1503
|
+
const glRenderTarget = renderTargetSystem.getGpuRenderTarget(renderTarget);
|
|
1504
|
+
this._resizeColor(renderTarget, glRenderTarget);
|
|
1505
|
+
if (renderTarget.stencil || renderTarget.depth) {
|
|
1506
|
+
this._resizeStencil(glRenderTarget);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
_initColor(renderTarget, glRenderTarget) {
|
|
1510
|
+
const renderer = this._renderer;
|
|
1511
|
+
const gl = renderer.gl;
|
|
1512
|
+
const resolveTargetFramebuffer = gl.createFramebuffer();
|
|
1513
|
+
glRenderTarget.resolveTargetFramebuffer = resolveTargetFramebuffer;
|
|
1514
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, resolveTargetFramebuffer);
|
|
1515
|
+
glRenderTarget.width = renderTarget.colorTexture.source.pixelWidth;
|
|
1516
|
+
glRenderTarget.height = renderTarget.colorTexture.source.pixelHeight;
|
|
1517
|
+
const colorTextures = renderTarget.colorTextures;
|
|
1518
|
+
colorTextures.forEach((colorTexture, i) => {
|
|
1519
|
+
const source = colorTexture.source;
|
|
1520
|
+
if (source.antialias) {
|
|
1521
|
+
if (renderer.context.supports.msaa) {
|
|
1522
|
+
glRenderTarget.msaa = true;
|
|
1523
|
+
} else {
|
|
1524
|
+
warn("[RenderTexture] Antialiasing on textures is not supported in WebGL1");
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
renderer.texture.bindSource(source, 0);
|
|
1528
|
+
const glSource = renderer.texture.getGlSource(source);
|
|
1529
|
+
const glTexture = glSource.texture;
|
|
1530
|
+
if (glSource.target === gl.TEXTURE_2D) {
|
|
1531
|
+
gl.framebufferTexture2D(
|
|
1532
|
+
gl.FRAMEBUFFER,
|
|
1533
|
+
gl.COLOR_ATTACHMENT0 + i,
|
|
1534
|
+
gl.TEXTURE_2D,
|
|
1535
|
+
glTexture,
|
|
1536
|
+
0
|
|
1537
|
+
);
|
|
1538
|
+
} else if (glSource.target === gl.TEXTURE_2D_ARRAY) {
|
|
1539
|
+
if (renderer.context.webGLVersion < 2) {
|
|
1540
|
+
throw new Error("[RenderTargetSystem] TEXTURE_2D_ARRAY requires WebGL2.");
|
|
1541
|
+
}
|
|
1542
|
+
gl.framebufferTextureLayer(
|
|
1543
|
+
gl.FRAMEBUFFER,
|
|
1544
|
+
gl.COLOR_ATTACHMENT0 + i,
|
|
1545
|
+
glTexture,
|
|
1546
|
+
0,
|
|
1547
|
+
0
|
|
1548
|
+
);
|
|
1549
|
+
} else if (glSource.target === gl.TEXTURE_CUBE_MAP) {
|
|
1550
|
+
gl.framebufferTexture2D(
|
|
1551
|
+
gl.FRAMEBUFFER,
|
|
1552
|
+
gl.COLOR_ATTACHMENT0 + i,
|
|
1553
|
+
gl.TEXTURE_CUBE_MAP_POSITIVE_X,
|
|
1554
|
+
glTexture,
|
|
1555
|
+
0
|
|
1556
|
+
);
|
|
1557
|
+
} else {
|
|
1558
|
+
throw new Error("[RenderTargetSystem] Unsupported texture target for framebuffer attachment.");
|
|
1559
|
+
}
|
|
1560
|
+
});
|
|
1561
|
+
if (glRenderTarget.msaa) {
|
|
1562
|
+
const viewFramebuffer = gl.createFramebuffer();
|
|
1563
|
+
glRenderTarget.framebuffer = viewFramebuffer;
|
|
1564
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, viewFramebuffer);
|
|
1565
|
+
renderTarget.colorTextures.forEach((_, i) => {
|
|
1566
|
+
const msaaRenderBuffer = gl.createRenderbuffer();
|
|
1567
|
+
glRenderTarget.msaaRenderBuffer[i] = msaaRenderBuffer;
|
|
1568
|
+
});
|
|
1569
|
+
} else {
|
|
1570
|
+
glRenderTarget.framebuffer = resolveTargetFramebuffer;
|
|
1571
|
+
}
|
|
1572
|
+
this._resizeColor(renderTarget, glRenderTarget);
|
|
1573
|
+
}
|
|
1574
|
+
_resizeColor(renderTarget, glRenderTarget) {
|
|
1575
|
+
const source = renderTarget.colorTexture.source;
|
|
1576
|
+
glRenderTarget.width = source.pixelWidth;
|
|
1577
|
+
glRenderTarget.height = source.pixelHeight;
|
|
1578
|
+
glRenderTarget._attachedMipLevel = 0;
|
|
1579
|
+
glRenderTarget._attachedLayer = 0;
|
|
1580
|
+
renderTarget.colorTextures.forEach((colorTexture, i) => {
|
|
1581
|
+
if (i === 0) return;
|
|
1582
|
+
colorTexture.source.resize(source.width, source.height, source._resolution);
|
|
1583
|
+
});
|
|
1584
|
+
if (glRenderTarget.msaa) {
|
|
1585
|
+
const renderer = this._renderer;
|
|
1586
|
+
const gl = renderer.gl;
|
|
1587
|
+
const viewFramebuffer = glRenderTarget.framebuffer;
|
|
1588
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, viewFramebuffer);
|
|
1589
|
+
renderTarget.colorTextures.forEach((colorTexture, i) => {
|
|
1590
|
+
const source2 = colorTexture.source;
|
|
1591
|
+
renderer.texture.bindSource(source2, 0);
|
|
1592
|
+
const glSource = renderer.texture.getGlSource(source2);
|
|
1593
|
+
const glInternalFormat = glSource.internalFormat;
|
|
1594
|
+
const msaaRenderBuffer = glRenderTarget.msaaRenderBuffer[i];
|
|
1595
|
+
gl.bindRenderbuffer(
|
|
1596
|
+
gl.RENDERBUFFER,
|
|
1597
|
+
msaaRenderBuffer
|
|
1598
|
+
);
|
|
1599
|
+
gl.renderbufferStorageMultisample(
|
|
1600
|
+
gl.RENDERBUFFER,
|
|
1601
|
+
4,
|
|
1602
|
+
glInternalFormat,
|
|
1603
|
+
source2.pixelWidth,
|
|
1604
|
+
source2.pixelHeight
|
|
1605
|
+
);
|
|
1606
|
+
gl.framebufferRenderbuffer(
|
|
1607
|
+
gl.FRAMEBUFFER,
|
|
1608
|
+
gl.COLOR_ATTACHMENT0 + i,
|
|
1609
|
+
gl.RENDERBUFFER,
|
|
1610
|
+
msaaRenderBuffer
|
|
1611
|
+
);
|
|
1612
|
+
});
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
_initStencil(glRenderTarget) {
|
|
1616
|
+
if (glRenderTarget.framebuffer === null) return;
|
|
1617
|
+
const gl = this._renderer.gl;
|
|
1618
|
+
const depthStencilRenderBuffer = gl.createRenderbuffer();
|
|
1619
|
+
glRenderTarget.depthStencilRenderBuffer = depthStencilRenderBuffer;
|
|
1620
|
+
gl.bindRenderbuffer(
|
|
1621
|
+
gl.RENDERBUFFER,
|
|
1622
|
+
depthStencilRenderBuffer
|
|
1623
|
+
);
|
|
1624
|
+
gl.framebufferRenderbuffer(
|
|
1625
|
+
gl.FRAMEBUFFER,
|
|
1626
|
+
gl.DEPTH_STENCIL_ATTACHMENT,
|
|
1627
|
+
gl.RENDERBUFFER,
|
|
1628
|
+
depthStencilRenderBuffer
|
|
1629
|
+
);
|
|
1630
|
+
this._resizeStencil(glRenderTarget);
|
|
1631
|
+
}
|
|
1632
|
+
_resizeStencil(glRenderTarget) {
|
|
1633
|
+
const gl = this._renderer.gl;
|
|
1634
|
+
gl.bindRenderbuffer(
|
|
1635
|
+
gl.RENDERBUFFER,
|
|
1636
|
+
glRenderTarget.depthStencilRenderBuffer
|
|
1637
|
+
);
|
|
1638
|
+
if (glRenderTarget.msaa) {
|
|
1639
|
+
gl.renderbufferStorageMultisample(
|
|
1640
|
+
gl.RENDERBUFFER,
|
|
1641
|
+
4,
|
|
1642
|
+
gl.DEPTH24_STENCIL8,
|
|
1643
|
+
glRenderTarget.width,
|
|
1644
|
+
glRenderTarget.height
|
|
1645
|
+
);
|
|
1646
|
+
} else {
|
|
1647
|
+
gl.renderbufferStorage(
|
|
1648
|
+
gl.RENDERBUFFER,
|
|
1649
|
+
this._renderer.context.webGLVersion === 2 ? gl.DEPTH24_STENCIL8 : gl.DEPTH_STENCIL,
|
|
1650
|
+
glRenderTarget.width,
|
|
1651
|
+
glRenderTarget.height
|
|
1652
|
+
);
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
prerender(renderTarget) {
|
|
1656
|
+
const resource = renderTarget.colorTexture.resource;
|
|
1657
|
+
if (this._renderer.context.multiView && CanvasSource.test(resource)) {
|
|
1658
|
+
this._renderer.context.ensureCanvasSize(resource);
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
postrender(renderTarget) {
|
|
1662
|
+
if (!this._renderer.context.multiView) return;
|
|
1663
|
+
if (CanvasSource.test(renderTarget.colorTexture.resource)) {
|
|
1664
|
+
const contextCanvas = this._renderer.context.canvas;
|
|
1665
|
+
const canvasSource = renderTarget.colorTexture;
|
|
1666
|
+
canvasSource.context2D.drawImage(
|
|
1667
|
+
contextCanvas,
|
|
1668
|
+
0,
|
|
1669
|
+
canvasSource.pixelHeight - contextCanvas.height
|
|
1670
|
+
);
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
_setDrawBuffers(renderTarget, gl) {
|
|
1674
|
+
const count = renderTarget.colorTextures.length;
|
|
1675
|
+
const bufferArray = this._drawBuffersCache[count];
|
|
1676
|
+
if (this._renderer.context.webGLVersion === 1) {
|
|
1677
|
+
const ext = this._renderer.context.extensions.drawBuffers;
|
|
1678
|
+
if (!ext) {
|
|
1679
|
+
warn("[RenderTexture] This WebGL1 context does not support rendering to multiple targets");
|
|
1680
|
+
} else {
|
|
1681
|
+
ext.drawBuffersWEBGL(bufferArray);
|
|
1682
|
+
}
|
|
1683
|
+
} else {
|
|
1684
|
+
gl.drawBuffers(bufferArray);
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
class GlRenderTargetSystem extends RenderTargetSystem {
|
|
1689
|
+
constructor(renderer) {
|
|
1690
|
+
super(renderer);
|
|
1691
|
+
this.adaptor = new GlRenderTargetAdaptor();
|
|
1692
|
+
this.adaptor.init(renderer, this);
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
GlRenderTargetSystem.extension = {
|
|
1696
|
+
type: [ExtensionType.WebGLSystem],
|
|
1697
|
+
name: "renderTarget"
|
|
1698
|
+
};
|
|
1699
|
+
function generateShaderSyncCode(shader, shaderSystem) {
|
|
1700
|
+
const funcFragments = [];
|
|
1701
|
+
const headerFragments = [`
|
|
1702
|
+
var g = s.groups;
|
|
1703
|
+
var sS = r.shader;
|
|
1704
|
+
var p = s.glProgram;
|
|
1705
|
+
var ugS = r.uniformGroup;
|
|
1706
|
+
var resources;
|
|
1707
|
+
`];
|
|
1708
|
+
let addedTextreSystem = false;
|
|
1709
|
+
let textureCount = 0;
|
|
1710
|
+
const programData = shaderSystem._getProgramData(shader.glProgram);
|
|
1711
|
+
for (const i in shader.groups) {
|
|
1712
|
+
const group = shader.groups[i];
|
|
1713
|
+
funcFragments.push(`
|
|
1714
|
+
resources = g[${i}].resources;
|
|
1715
|
+
`);
|
|
1716
|
+
for (const j in group.resources) {
|
|
1717
|
+
const resource = group.resources[j];
|
|
1718
|
+
if (resource instanceof UniformGroup) {
|
|
1719
|
+
if (resource.ubo) {
|
|
1720
|
+
const resName = shader._uniformBindMap[i][Number(j)];
|
|
1721
|
+
funcFragments.push(`
|
|
1722
|
+
sS.bindUniformBlock(
|
|
1723
|
+
resources[${j}],
|
|
1724
|
+
'${resName}',
|
|
1725
|
+
${shader.glProgram._uniformBlockData[resName].index}
|
|
1726
|
+
);
|
|
1727
|
+
`);
|
|
1728
|
+
} else {
|
|
1729
|
+
funcFragments.push(`
|
|
1730
|
+
ugS.updateUniformGroup(resources[${j}], p, sD);
|
|
1731
|
+
`);
|
|
1732
|
+
}
|
|
1733
|
+
} else if (resource instanceof BufferResource) {
|
|
1734
|
+
const resName = shader._uniformBindMap[i][Number(j)];
|
|
1735
|
+
funcFragments.push(`
|
|
1736
|
+
sS.bindUniformBlock(
|
|
1737
|
+
resources[${j}],
|
|
1738
|
+
'${resName}',
|
|
1739
|
+
${shader.glProgram._uniformBlockData[resName].index}
|
|
1740
|
+
);
|
|
1741
|
+
`);
|
|
1742
|
+
} else if (resource instanceof TextureSource) {
|
|
1743
|
+
const uniformName = shader._uniformBindMap[i][j];
|
|
1744
|
+
const uniformData = programData.uniformData[uniformName];
|
|
1745
|
+
if (uniformData) {
|
|
1746
|
+
if (!addedTextreSystem) {
|
|
1747
|
+
addedTextreSystem = true;
|
|
1748
|
+
headerFragments.push(`
|
|
1749
|
+
var tS = r.texture;
|
|
1750
|
+
`);
|
|
1751
|
+
}
|
|
1752
|
+
shaderSystem._gl.uniform1i(uniformData.location, textureCount);
|
|
1753
|
+
funcFragments.push(`
|
|
1754
|
+
tS.bind(resources[${j}], ${textureCount});
|
|
1755
|
+
`);
|
|
1756
|
+
textureCount++;
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
const functionSource = [...headerFragments, ...funcFragments].join("\n");
|
|
1762
|
+
return new Function("r", "s", "sD", functionSource);
|
|
1763
|
+
}
|
|
1764
|
+
class GlProgramData {
|
|
1765
|
+
/**
|
|
1766
|
+
* Makes a new Pixi program.
|
|
1767
|
+
* @param program - webgl program
|
|
1768
|
+
* @param uniformData - uniforms
|
|
1769
|
+
*/
|
|
1770
|
+
constructor(program, uniformData) {
|
|
1771
|
+
this.program = program;
|
|
1772
|
+
this.uniformData = uniformData;
|
|
1773
|
+
this.uniformGroups = {};
|
|
1774
|
+
this.uniformDirtyGroups = {};
|
|
1775
|
+
this.uniformBlockBindings = {};
|
|
1776
|
+
}
|
|
1777
|
+
/** Destroys this program. */
|
|
1778
|
+
destroy() {
|
|
1779
|
+
this.uniformData = null;
|
|
1780
|
+
this.uniformGroups = null;
|
|
1781
|
+
this.uniformDirtyGroups = null;
|
|
1782
|
+
this.uniformBlockBindings = null;
|
|
1783
|
+
this.program = null;
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
function compileShader(gl, type, src) {
|
|
1787
|
+
const shader = gl.createShader(type);
|
|
1788
|
+
gl.shaderSource(shader, src);
|
|
1789
|
+
gl.compileShader(shader);
|
|
1790
|
+
return shader;
|
|
1791
|
+
}
|
|
1792
|
+
function booleanArray(size) {
|
|
1793
|
+
const array = new Array(size);
|
|
1794
|
+
for (let i = 0; i < array.length; i++) {
|
|
1795
|
+
array[i] = false;
|
|
1796
|
+
}
|
|
1797
|
+
return array;
|
|
1798
|
+
}
|
|
1799
|
+
function defaultValue(type, size) {
|
|
1800
|
+
switch (type) {
|
|
1801
|
+
case "float":
|
|
1802
|
+
return 0;
|
|
1803
|
+
case "vec2":
|
|
1804
|
+
return new Float32Array(2 * size);
|
|
1805
|
+
case "vec3":
|
|
1806
|
+
return new Float32Array(3 * size);
|
|
1807
|
+
case "vec4":
|
|
1808
|
+
return new Float32Array(4 * size);
|
|
1809
|
+
case "int":
|
|
1810
|
+
case "uint":
|
|
1811
|
+
case "sampler2D":
|
|
1812
|
+
case "sampler2DArray":
|
|
1813
|
+
return 0;
|
|
1814
|
+
case "ivec2":
|
|
1815
|
+
return new Int32Array(2 * size);
|
|
1816
|
+
case "ivec3":
|
|
1817
|
+
return new Int32Array(3 * size);
|
|
1818
|
+
case "ivec4":
|
|
1819
|
+
return new Int32Array(4 * size);
|
|
1820
|
+
case "uvec2":
|
|
1821
|
+
return new Uint32Array(2 * size);
|
|
1822
|
+
case "uvec3":
|
|
1823
|
+
return new Uint32Array(3 * size);
|
|
1824
|
+
case "uvec4":
|
|
1825
|
+
return new Uint32Array(4 * size);
|
|
1826
|
+
case "bool":
|
|
1827
|
+
return false;
|
|
1828
|
+
case "bvec2":
|
|
1829
|
+
return booleanArray(2 * size);
|
|
1830
|
+
case "bvec3":
|
|
1831
|
+
return booleanArray(3 * size);
|
|
1832
|
+
case "bvec4":
|
|
1833
|
+
return booleanArray(4 * size);
|
|
1834
|
+
case "mat2":
|
|
1835
|
+
return new Float32Array([
|
|
1836
|
+
1,
|
|
1837
|
+
0,
|
|
1838
|
+
0,
|
|
1839
|
+
1
|
|
1840
|
+
]);
|
|
1841
|
+
case "mat3":
|
|
1842
|
+
return new Float32Array([
|
|
1843
|
+
1,
|
|
1844
|
+
0,
|
|
1845
|
+
0,
|
|
1846
|
+
0,
|
|
1847
|
+
1,
|
|
1848
|
+
0,
|
|
1849
|
+
0,
|
|
1850
|
+
0,
|
|
1851
|
+
1
|
|
1852
|
+
]);
|
|
1853
|
+
case "mat4":
|
|
1854
|
+
return new Float32Array([
|
|
1855
|
+
1,
|
|
1856
|
+
0,
|
|
1857
|
+
0,
|
|
1858
|
+
0,
|
|
1859
|
+
0,
|
|
1860
|
+
1,
|
|
1861
|
+
0,
|
|
1862
|
+
0,
|
|
1863
|
+
0,
|
|
1864
|
+
0,
|
|
1865
|
+
1,
|
|
1866
|
+
0,
|
|
1867
|
+
0,
|
|
1868
|
+
0,
|
|
1869
|
+
0,
|
|
1870
|
+
1
|
|
1871
|
+
]);
|
|
1872
|
+
}
|
|
1873
|
+
return null;
|
|
1874
|
+
}
|
|
1875
|
+
let GL_TABLE = null;
|
|
1876
|
+
const GL_TO_GLSL_TYPES = {
|
|
1877
|
+
FLOAT: "float",
|
|
1878
|
+
FLOAT_VEC2: "vec2",
|
|
1879
|
+
FLOAT_VEC3: "vec3",
|
|
1880
|
+
FLOAT_VEC4: "vec4",
|
|
1881
|
+
INT: "int",
|
|
1882
|
+
INT_VEC2: "ivec2",
|
|
1883
|
+
INT_VEC3: "ivec3",
|
|
1884
|
+
INT_VEC4: "ivec4",
|
|
1885
|
+
UNSIGNED_INT: "uint",
|
|
1886
|
+
UNSIGNED_INT_VEC2: "uvec2",
|
|
1887
|
+
UNSIGNED_INT_VEC3: "uvec3",
|
|
1888
|
+
UNSIGNED_INT_VEC4: "uvec4",
|
|
1889
|
+
BOOL: "bool",
|
|
1890
|
+
BOOL_VEC2: "bvec2",
|
|
1891
|
+
BOOL_VEC3: "bvec3",
|
|
1892
|
+
BOOL_VEC4: "bvec4",
|
|
1893
|
+
FLOAT_MAT2: "mat2",
|
|
1894
|
+
FLOAT_MAT3: "mat3",
|
|
1895
|
+
FLOAT_MAT4: "mat4",
|
|
1896
|
+
SAMPLER_2D: "sampler2D",
|
|
1897
|
+
INT_SAMPLER_2D: "sampler2D",
|
|
1898
|
+
UNSIGNED_INT_SAMPLER_2D: "sampler2D",
|
|
1899
|
+
SAMPLER_CUBE: "samplerCube",
|
|
1900
|
+
INT_SAMPLER_CUBE: "samplerCube",
|
|
1901
|
+
UNSIGNED_INT_SAMPLER_CUBE: "samplerCube",
|
|
1902
|
+
SAMPLER_2D_ARRAY: "sampler2DArray",
|
|
1903
|
+
INT_SAMPLER_2D_ARRAY: "sampler2DArray",
|
|
1904
|
+
UNSIGNED_INT_SAMPLER_2D_ARRAY: "sampler2DArray"
|
|
1905
|
+
};
|
|
1906
|
+
const GLSL_TO_VERTEX_TYPES = {
|
|
1907
|
+
float: "float32",
|
|
1908
|
+
vec2: "float32x2",
|
|
1909
|
+
vec3: "float32x3",
|
|
1910
|
+
vec4: "float32x4",
|
|
1911
|
+
int: "sint32",
|
|
1912
|
+
ivec2: "sint32x2",
|
|
1913
|
+
ivec3: "sint32x3",
|
|
1914
|
+
ivec4: "sint32x4",
|
|
1915
|
+
uint: "uint32",
|
|
1916
|
+
uvec2: "uint32x2",
|
|
1917
|
+
uvec3: "uint32x3",
|
|
1918
|
+
uvec4: "uint32x4",
|
|
1919
|
+
bool: "uint32",
|
|
1920
|
+
bvec2: "uint32x2",
|
|
1921
|
+
bvec3: "uint32x3",
|
|
1922
|
+
bvec4: "uint32x4"
|
|
1923
|
+
};
|
|
1924
|
+
function mapType(gl, type) {
|
|
1925
|
+
if (!GL_TABLE) {
|
|
1926
|
+
const typeNames = Object.keys(GL_TO_GLSL_TYPES);
|
|
1927
|
+
GL_TABLE = {};
|
|
1928
|
+
for (let i = 0; i < typeNames.length; ++i) {
|
|
1929
|
+
const tn = typeNames[i];
|
|
1930
|
+
GL_TABLE[gl[tn]] = GL_TO_GLSL_TYPES[tn];
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
return GL_TABLE[type];
|
|
1934
|
+
}
|
|
1935
|
+
function mapGlToVertexFormat(gl, type) {
|
|
1936
|
+
const typeValue = mapType(gl, type);
|
|
1937
|
+
return GLSL_TO_VERTEX_TYPES[typeValue] || "float32";
|
|
1938
|
+
}
|
|
1939
|
+
function extractAttributesFromGlProgram(program, gl, sortAttributes = false) {
|
|
1940
|
+
const attributes = {};
|
|
1941
|
+
const totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
|
|
1942
|
+
for (let i = 0; i < totalAttributes; i++) {
|
|
1943
|
+
const attribData = gl.getActiveAttrib(program, i);
|
|
1944
|
+
if (attribData.name.startsWith("gl_")) {
|
|
1945
|
+
continue;
|
|
1946
|
+
}
|
|
1947
|
+
const format = mapGlToVertexFormat(gl, attribData.type);
|
|
1948
|
+
attributes[attribData.name] = {
|
|
1949
|
+
location: 0,
|
|
1950
|
+
// set further down..
|
|
1951
|
+
format,
|
|
1952
|
+
stride: getAttributeInfoFromFormat(format).stride,
|
|
1953
|
+
offset: 0,
|
|
1954
|
+
instance: false,
|
|
1955
|
+
start: 0
|
|
1956
|
+
};
|
|
1957
|
+
}
|
|
1958
|
+
const keys = Object.keys(attributes);
|
|
1959
|
+
if (sortAttributes) {
|
|
1960
|
+
keys.sort((a, b) => a > b ? 1 : -1);
|
|
1961
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1962
|
+
attributes[keys[i]].location = i;
|
|
1963
|
+
gl.bindAttribLocation(program, i, keys[i]);
|
|
1964
|
+
}
|
|
1965
|
+
gl.linkProgram(program);
|
|
1966
|
+
} else {
|
|
1967
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1968
|
+
attributes[keys[i]].location = gl.getAttribLocation(program, keys[i]);
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
return attributes;
|
|
1972
|
+
}
|
|
1973
|
+
function getUboData(program, gl) {
|
|
1974
|
+
if (!gl.ACTIVE_UNIFORM_BLOCKS) return {};
|
|
1975
|
+
const uniformBlocks = {};
|
|
1976
|
+
const totalUniformsBlocks = gl.getProgramParameter(program, gl.ACTIVE_UNIFORM_BLOCKS);
|
|
1977
|
+
for (let i = 0; i < totalUniformsBlocks; i++) {
|
|
1978
|
+
const name = gl.getActiveUniformBlockName(program, i);
|
|
1979
|
+
const uniformBlockIndex = gl.getUniformBlockIndex(program, name);
|
|
1980
|
+
const size = gl.getActiveUniformBlockParameter(program, i, gl.UNIFORM_BLOCK_DATA_SIZE);
|
|
1981
|
+
uniformBlocks[name] = {
|
|
1982
|
+
name,
|
|
1983
|
+
index: uniformBlockIndex,
|
|
1984
|
+
size
|
|
1985
|
+
};
|
|
1986
|
+
}
|
|
1987
|
+
return uniformBlocks;
|
|
1988
|
+
}
|
|
1989
|
+
function getUniformData(program, gl) {
|
|
1990
|
+
const uniforms = {};
|
|
1991
|
+
const totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
|
|
1992
|
+
for (let i = 0; i < totalUniforms; i++) {
|
|
1993
|
+
const uniformData = gl.getActiveUniform(program, i);
|
|
1994
|
+
const name = uniformData.name.replace(/\[.*?\]$/, "");
|
|
1995
|
+
const isArray = !!uniformData.name.match(/\[.*?\]$/);
|
|
1996
|
+
const type = mapType(gl, uniformData.type);
|
|
1997
|
+
uniforms[name] = {
|
|
1998
|
+
name,
|
|
1999
|
+
index: i,
|
|
2000
|
+
type,
|
|
2001
|
+
size: uniformData.size,
|
|
2002
|
+
isArray,
|
|
2003
|
+
value: defaultValue(type, uniformData.size)
|
|
2004
|
+
};
|
|
2005
|
+
}
|
|
2006
|
+
return uniforms;
|
|
2007
|
+
}
|
|
2008
|
+
function logPrettyShaderError(gl, shader) {
|
|
2009
|
+
const shaderSrc = gl.getShaderSource(shader).split("\n").map((line, index) => `${index}: ${line}`);
|
|
2010
|
+
const shaderLog = gl.getShaderInfoLog(shader);
|
|
2011
|
+
const splitShader = shaderLog.split("\n");
|
|
2012
|
+
const dedupe = {};
|
|
2013
|
+
const lineNumbers = splitShader.map((line) => parseFloat(line.replace(/^ERROR\: 0\:([\d]+)\:.*$/, "$1"))).filter((n) => {
|
|
2014
|
+
if (n && !dedupe[n]) {
|
|
2015
|
+
dedupe[n] = true;
|
|
2016
|
+
return true;
|
|
2017
|
+
}
|
|
2018
|
+
return false;
|
|
2019
|
+
});
|
|
2020
|
+
const logArgs = [""];
|
|
2021
|
+
lineNumbers.forEach((number) => {
|
|
2022
|
+
shaderSrc[number - 1] = `%c${shaderSrc[number - 1]}%c`;
|
|
2023
|
+
logArgs.push("background: #FF0000; color:#FFFFFF; font-size: 10px", "font-size: 10px");
|
|
2024
|
+
});
|
|
2025
|
+
const fragmentSourceToLog = shaderSrc.join("\n");
|
|
2026
|
+
logArgs[0] = fragmentSourceToLog;
|
|
2027
|
+
console.error(shaderLog);
|
|
2028
|
+
console.groupCollapsed("click to view full shader code");
|
|
2029
|
+
console.warn(...logArgs);
|
|
2030
|
+
console.groupEnd();
|
|
2031
|
+
}
|
|
2032
|
+
function logProgramError(gl, program, vertexShader, fragmentShader) {
|
|
2033
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
2034
|
+
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
|
|
2035
|
+
logPrettyShaderError(gl, vertexShader);
|
|
2036
|
+
}
|
|
2037
|
+
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
|
|
2038
|
+
logPrettyShaderError(gl, fragmentShader);
|
|
2039
|
+
}
|
|
2040
|
+
console.error("PixiJS Error: Could not initialize shader.");
|
|
2041
|
+
if (gl.getProgramInfoLog(program) !== "") {
|
|
2042
|
+
console.warn("PixiJS Warning: gl.getProgramInfoLog()", gl.getProgramInfoLog(program));
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
function generateProgram(gl, program) {
|
|
2047
|
+
const glVertShader = compileShader(gl, gl.VERTEX_SHADER, program.vertex);
|
|
2048
|
+
const glFragShader = compileShader(gl, gl.FRAGMENT_SHADER, program.fragment);
|
|
2049
|
+
const webGLProgram = gl.createProgram();
|
|
2050
|
+
gl.attachShader(webGLProgram, glVertShader);
|
|
2051
|
+
gl.attachShader(webGLProgram, glFragShader);
|
|
2052
|
+
const transformFeedbackVaryings = program.transformFeedbackVaryings;
|
|
2053
|
+
if (transformFeedbackVaryings) {
|
|
2054
|
+
if (typeof gl.transformFeedbackVaryings !== "function") {
|
|
2055
|
+
warn(`TransformFeedback is not supported but TransformFeedbackVaryings are given.`);
|
|
2056
|
+
} else {
|
|
2057
|
+
gl.transformFeedbackVaryings(
|
|
2058
|
+
webGLProgram,
|
|
2059
|
+
transformFeedbackVaryings.names,
|
|
2060
|
+
transformFeedbackVaryings.bufferMode === "separate" ? gl.SEPARATE_ATTRIBS : gl.INTERLEAVED_ATTRIBS
|
|
2061
|
+
);
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
gl.linkProgram(webGLProgram);
|
|
2065
|
+
if (!gl.getProgramParameter(webGLProgram, gl.LINK_STATUS)) {
|
|
2066
|
+
logProgramError(gl, webGLProgram, glVertShader, glFragShader);
|
|
2067
|
+
}
|
|
2068
|
+
program._attributeData = extractAttributesFromGlProgram(
|
|
2069
|
+
webGLProgram,
|
|
2070
|
+
gl,
|
|
2071
|
+
!/^[ \t]*#[ \t]*version[ \t]+300[ \t]+es[ \t]*$/m.test(program.vertex)
|
|
2072
|
+
);
|
|
2073
|
+
program._uniformData = getUniformData(webGLProgram, gl);
|
|
2074
|
+
program._uniformBlockData = getUboData(webGLProgram, gl);
|
|
2075
|
+
gl.deleteShader(glVertShader);
|
|
2076
|
+
gl.deleteShader(glFragShader);
|
|
2077
|
+
const uniformData = {};
|
|
2078
|
+
for (const i in program._uniformData) {
|
|
2079
|
+
const data = program._uniformData[i];
|
|
2080
|
+
uniformData[i] = {
|
|
2081
|
+
location: gl.getUniformLocation(webGLProgram, i),
|
|
2082
|
+
value: defaultValue(data.type, data.size)
|
|
2083
|
+
};
|
|
2084
|
+
}
|
|
2085
|
+
const glProgram = new GlProgramData(webGLProgram, uniformData);
|
|
2086
|
+
return glProgram;
|
|
2087
|
+
}
|
|
2088
|
+
const defaultSyncData = {
|
|
2089
|
+
textureCount: 0,
|
|
2090
|
+
blockIndex: 0
|
|
2091
|
+
};
|
|
2092
|
+
class GlShaderSystem {
|
|
2093
|
+
constructor(renderer) {
|
|
2094
|
+
this._activeProgram = null;
|
|
2095
|
+
this._programDataHash = /* @__PURE__ */ Object.create(null);
|
|
2096
|
+
this._shaderSyncFunctions = /* @__PURE__ */ Object.create(null);
|
|
2097
|
+
this._renderer = renderer;
|
|
2098
|
+
}
|
|
2099
|
+
contextChange(gl) {
|
|
2100
|
+
this._gl = gl;
|
|
2101
|
+
this._programDataHash = /* @__PURE__ */ Object.create(null);
|
|
2102
|
+
this._shaderSyncFunctions = /* @__PURE__ */ Object.create(null);
|
|
2103
|
+
this._activeProgram = null;
|
|
2104
|
+
}
|
|
2105
|
+
/**
|
|
2106
|
+
* Changes the current shader to the one given in parameter.
|
|
2107
|
+
* @param shader - the new shader
|
|
2108
|
+
* @param skipSync - false if the shader should automatically sync its uniforms.
|
|
2109
|
+
* @returns the glProgram that belongs to the shader.
|
|
2110
|
+
*/
|
|
2111
|
+
bind(shader, skipSync) {
|
|
2112
|
+
this._setProgram(shader.glProgram);
|
|
2113
|
+
if (skipSync) return;
|
|
2114
|
+
defaultSyncData.textureCount = 0;
|
|
2115
|
+
defaultSyncData.blockIndex = 0;
|
|
2116
|
+
let syncFunction = this._shaderSyncFunctions[shader.glProgram._key];
|
|
2117
|
+
if (!syncFunction) {
|
|
2118
|
+
syncFunction = this._shaderSyncFunctions[shader.glProgram._key] = this._generateShaderSync(shader, this);
|
|
2119
|
+
}
|
|
2120
|
+
this._renderer.buffer.nextBindBase(!!shader.glProgram.transformFeedbackVaryings);
|
|
2121
|
+
syncFunction(this._renderer, shader, defaultSyncData);
|
|
2122
|
+
}
|
|
2123
|
+
/**
|
|
2124
|
+
* Updates the uniform group.
|
|
2125
|
+
* @param uniformGroup - the uniform group to update
|
|
2126
|
+
*/
|
|
2127
|
+
updateUniformGroup(uniformGroup) {
|
|
2128
|
+
this._renderer.uniformGroup.updateUniformGroup(uniformGroup, this._activeProgram, defaultSyncData);
|
|
2129
|
+
}
|
|
2130
|
+
/**
|
|
2131
|
+
* Binds a uniform block to the shader.
|
|
2132
|
+
* @param uniformGroup - the uniform group to bind
|
|
2133
|
+
* @param name - the name of the uniform block
|
|
2134
|
+
* @param index - the index of the uniform block
|
|
2135
|
+
*/
|
|
2136
|
+
bindUniformBlock(uniformGroup, name, index = 0) {
|
|
2137
|
+
const bufferSystem = this._renderer.buffer;
|
|
2138
|
+
const programData = this._getProgramData(this._activeProgram);
|
|
2139
|
+
const isBufferResource = uniformGroup._bufferResource;
|
|
2140
|
+
if (!isBufferResource) {
|
|
2141
|
+
this._renderer.ubo.updateUniformGroup(uniformGroup);
|
|
2142
|
+
}
|
|
2143
|
+
const buffer = uniformGroup.buffer;
|
|
2144
|
+
const glBuffer = bufferSystem.updateBuffer(buffer);
|
|
2145
|
+
const boundLocation = bufferSystem.freeLocationForBufferBase(glBuffer);
|
|
2146
|
+
if (isBufferResource) {
|
|
2147
|
+
const { offset, size } = uniformGroup;
|
|
2148
|
+
if (offset === 0 && size === buffer.data.byteLength) {
|
|
2149
|
+
bufferSystem.bindBufferBase(glBuffer, boundLocation);
|
|
2150
|
+
} else {
|
|
2151
|
+
bufferSystem.bindBufferRange(glBuffer, boundLocation, offset);
|
|
2152
|
+
}
|
|
2153
|
+
} else if (bufferSystem.getLastBindBaseLocation(glBuffer) !== boundLocation) {
|
|
2154
|
+
bufferSystem.bindBufferBase(glBuffer, boundLocation);
|
|
2155
|
+
}
|
|
2156
|
+
const uniformBlockIndex = this._activeProgram._uniformBlockData[name].index;
|
|
2157
|
+
if (programData.uniformBlockBindings[index] === boundLocation) return;
|
|
2158
|
+
programData.uniformBlockBindings[index] = boundLocation;
|
|
2159
|
+
this._renderer.gl.uniformBlockBinding(programData.program, uniformBlockIndex, boundLocation);
|
|
2160
|
+
}
|
|
2161
|
+
_setProgram(program) {
|
|
2162
|
+
if (this._activeProgram === program) return;
|
|
2163
|
+
this._activeProgram = program;
|
|
2164
|
+
const programData = this._getProgramData(program);
|
|
2165
|
+
this._gl.useProgram(programData.program);
|
|
2166
|
+
}
|
|
2167
|
+
/**
|
|
2168
|
+
* @param program - the program to get the data for
|
|
2169
|
+
* @internal
|
|
2170
|
+
*/
|
|
2171
|
+
_getProgramData(program) {
|
|
2172
|
+
return this._programDataHash[program._key] || this._createProgramData(program);
|
|
2173
|
+
}
|
|
2174
|
+
_createProgramData(program) {
|
|
2175
|
+
const key = program._key;
|
|
2176
|
+
this._programDataHash[key] = generateProgram(this._gl, program);
|
|
2177
|
+
return this._programDataHash[key];
|
|
2178
|
+
}
|
|
2179
|
+
destroy() {
|
|
2180
|
+
for (const key of Object.keys(this._programDataHash)) {
|
|
2181
|
+
this._programDataHash[key].destroy();
|
|
2182
|
+
}
|
|
2183
|
+
this._programDataHash = null;
|
|
2184
|
+
this._shaderSyncFunctions = null;
|
|
2185
|
+
this._activeProgram = null;
|
|
2186
|
+
this._renderer = null;
|
|
2187
|
+
this._gl = null;
|
|
2188
|
+
}
|
|
2189
|
+
/**
|
|
2190
|
+
* Creates a function that can be executed that will sync the shader as efficiently as possible.
|
|
2191
|
+
* Overridden by the unsafe eval package if you don't want eval used in your project.
|
|
2192
|
+
* @param shader - the shader to generate the sync function for
|
|
2193
|
+
* @param shaderSystem - the shader system to use
|
|
2194
|
+
* @returns - the generated sync function
|
|
2195
|
+
* @ignore
|
|
2196
|
+
*/
|
|
2197
|
+
_generateShaderSync(shader, shaderSystem) {
|
|
2198
|
+
return generateShaderSyncCode(shader, shaderSystem);
|
|
2199
|
+
}
|
|
2200
|
+
resetState() {
|
|
2201
|
+
this._activeProgram = null;
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
GlShaderSystem.extension = {
|
|
2205
|
+
type: [
|
|
2206
|
+
ExtensionType.WebGLSystem
|
|
2207
|
+
],
|
|
2208
|
+
name: "shader"
|
|
2209
|
+
};
|
|
2210
|
+
const UNIFORM_TO_SINGLE_SETTERS = {
|
|
2211
|
+
f32: `if (cv !== v) {
|
|
2212
|
+
cu.value = v;
|
|
2213
|
+
gl.uniform1f(location, v);
|
|
2214
|
+
}`,
|
|
2215
|
+
"vec2<f32>": `if (cv[0] !== v[0] || cv[1] !== v[1]) {
|
|
2216
|
+
cv[0] = v[0];
|
|
2217
|
+
cv[1] = v[1];
|
|
2218
|
+
gl.uniform2f(location, v[0], v[1]);
|
|
2219
|
+
}`,
|
|
2220
|
+
"vec3<f32>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2]) {
|
|
2221
|
+
cv[0] = v[0];
|
|
2222
|
+
cv[1] = v[1];
|
|
2223
|
+
cv[2] = v[2];
|
|
2224
|
+
gl.uniform3f(location, v[0], v[1], v[2]);
|
|
2225
|
+
}`,
|
|
2226
|
+
"vec4<f32>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2] || cv[3] !== v[3]) {
|
|
2227
|
+
cv[0] = v[0];
|
|
2228
|
+
cv[1] = v[1];
|
|
2229
|
+
cv[2] = v[2];
|
|
2230
|
+
cv[3] = v[3];
|
|
2231
|
+
gl.uniform4f(location, v[0], v[1], v[2], v[3]);
|
|
2232
|
+
}`,
|
|
2233
|
+
i32: `if (cv !== v) {
|
|
2234
|
+
cu.value = v;
|
|
2235
|
+
gl.uniform1i(location, v);
|
|
2236
|
+
}`,
|
|
2237
|
+
"vec2<i32>": `if (cv[0] !== v[0] || cv[1] !== v[1]) {
|
|
2238
|
+
cv[0] = v[0];
|
|
2239
|
+
cv[1] = v[1];
|
|
2240
|
+
gl.uniform2i(location, v[0], v[1]);
|
|
2241
|
+
}`,
|
|
2242
|
+
"vec3<i32>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2]) {
|
|
2243
|
+
cv[0] = v[0];
|
|
2244
|
+
cv[1] = v[1];
|
|
2245
|
+
cv[2] = v[2];
|
|
2246
|
+
gl.uniform3i(location, v[0], v[1], v[2]);
|
|
2247
|
+
}`,
|
|
2248
|
+
"vec4<i32>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2] || cv[3] !== v[3]) {
|
|
2249
|
+
cv[0] = v[0];
|
|
2250
|
+
cv[1] = v[1];
|
|
2251
|
+
cv[2] = v[2];
|
|
2252
|
+
cv[3] = v[3];
|
|
2253
|
+
gl.uniform4i(location, v[0], v[1], v[2], v[3]);
|
|
2254
|
+
}`,
|
|
2255
|
+
u32: `if (cv !== v) {
|
|
2256
|
+
cu.value = v;
|
|
2257
|
+
gl.uniform1ui(location, v);
|
|
2258
|
+
}`,
|
|
2259
|
+
"vec2<u32>": `if (cv[0] !== v[0] || cv[1] !== v[1]) {
|
|
2260
|
+
cv[0] = v[0];
|
|
2261
|
+
cv[1] = v[1];
|
|
2262
|
+
gl.uniform2ui(location, v[0], v[1]);
|
|
2263
|
+
}`,
|
|
2264
|
+
"vec3<u32>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2]) {
|
|
2265
|
+
cv[0] = v[0];
|
|
2266
|
+
cv[1] = v[1];
|
|
2267
|
+
cv[2] = v[2];
|
|
2268
|
+
gl.uniform3ui(location, v[0], v[1], v[2]);
|
|
2269
|
+
}`,
|
|
2270
|
+
"vec4<u32>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2] || cv[3] !== v[3]) {
|
|
2271
|
+
cv[0] = v[0];
|
|
2272
|
+
cv[1] = v[1];
|
|
2273
|
+
cv[2] = v[2];
|
|
2274
|
+
cv[3] = v[3];
|
|
2275
|
+
gl.uniform4ui(location, v[0], v[1], v[2], v[3]);
|
|
2276
|
+
}`,
|
|
2277
|
+
bool: `if (cv !== v) {
|
|
2278
|
+
cu.value = v;
|
|
2279
|
+
gl.uniform1i(location, v);
|
|
2280
|
+
}`,
|
|
2281
|
+
"vec2<bool>": `if (cv[0] !== v[0] || cv[1] !== v[1]) {
|
|
2282
|
+
cv[0] = v[0];
|
|
2283
|
+
cv[1] = v[1];
|
|
2284
|
+
gl.uniform2i(location, v[0], v[1]);
|
|
2285
|
+
}`,
|
|
2286
|
+
"vec3<bool>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2]) {
|
|
2287
|
+
cv[0] = v[0];
|
|
2288
|
+
cv[1] = v[1];
|
|
2289
|
+
cv[2] = v[2];
|
|
2290
|
+
gl.uniform3i(location, v[0], v[1], v[2]);
|
|
2291
|
+
}`,
|
|
2292
|
+
"vec4<bool>": `if (cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2] || cv[3] !== v[3]) {
|
|
2293
|
+
cv[0] = v[0];
|
|
2294
|
+
cv[1] = v[1];
|
|
2295
|
+
cv[2] = v[2];
|
|
2296
|
+
cv[3] = v[3];
|
|
2297
|
+
gl.uniform4i(location, v[0], v[1], v[2], v[3]);
|
|
2298
|
+
}`,
|
|
2299
|
+
"mat2x2<f32>": `gl.uniformMatrix2fv(location, false, v);`,
|
|
2300
|
+
"mat3x3<f32>": `gl.uniformMatrix3fv(location, false, v);`,
|
|
2301
|
+
"mat4x4<f32>": `gl.uniformMatrix4fv(location, false, v);`
|
|
2302
|
+
};
|
|
2303
|
+
const UNIFORM_TO_ARRAY_SETTERS = {
|
|
2304
|
+
f32: `gl.uniform1fv(location, v);`,
|
|
2305
|
+
"vec2<f32>": `gl.uniform2fv(location, v);`,
|
|
2306
|
+
"vec3<f32>": `gl.uniform3fv(location, v);`,
|
|
2307
|
+
"vec4<f32>": `gl.uniform4fv(location, v);`,
|
|
2308
|
+
"mat2x2<f32>": `gl.uniformMatrix2fv(location, false, v);`,
|
|
2309
|
+
"mat3x3<f32>": `gl.uniformMatrix3fv(location, false, v);`,
|
|
2310
|
+
"mat4x4<f32>": `gl.uniformMatrix4fv(location, false, v);`,
|
|
2311
|
+
i32: `gl.uniform1iv(location, v);`,
|
|
2312
|
+
"vec2<i32>": `gl.uniform2iv(location, v);`,
|
|
2313
|
+
"vec3<i32>": `gl.uniform3iv(location, v);`,
|
|
2314
|
+
"vec4<i32>": `gl.uniform4iv(location, v);`,
|
|
2315
|
+
u32: `gl.uniform1iv(location, v);`,
|
|
2316
|
+
"vec2<u32>": `gl.uniform2iv(location, v);`,
|
|
2317
|
+
"vec3<u32>": `gl.uniform3iv(location, v);`,
|
|
2318
|
+
"vec4<u32>": `gl.uniform4iv(location, v);`,
|
|
2319
|
+
bool: `gl.uniform1iv(location, v);`,
|
|
2320
|
+
"vec2<bool>": `gl.uniform2iv(location, v);`,
|
|
2321
|
+
"vec3<bool>": `gl.uniform3iv(location, v);`,
|
|
2322
|
+
"vec4<bool>": `gl.uniform4iv(location, v);`
|
|
2323
|
+
};
|
|
2324
|
+
function generateUniformsSync(group, uniformData) {
|
|
2325
|
+
const funcFragments = [`
|
|
2326
|
+
var v = null;
|
|
2327
|
+
var cv = null;
|
|
2328
|
+
var cu = null;
|
|
2329
|
+
var t = 0;
|
|
2330
|
+
var gl = renderer.gl;
|
|
2331
|
+
var name = null;
|
|
2332
|
+
`];
|
|
2333
|
+
for (const i in group.uniforms) {
|
|
2334
|
+
if (!uniformData[i]) {
|
|
2335
|
+
if (group.uniforms[i] instanceof UniformGroup) {
|
|
2336
|
+
if (group.uniforms[i].ubo) {
|
|
2337
|
+
funcFragments.push(`
|
|
2338
|
+
renderer.shader.bindUniformBlock(uv.${i}, "${i}");
|
|
2339
|
+
`);
|
|
2340
|
+
} else {
|
|
2341
|
+
funcFragments.push(`
|
|
2342
|
+
renderer.shader.updateUniformGroup(uv.${i});
|
|
2343
|
+
`);
|
|
2344
|
+
}
|
|
2345
|
+
} else if (group.uniforms[i] instanceof BufferResource) {
|
|
2346
|
+
funcFragments.push(`
|
|
2347
|
+
renderer.shader.bindBufferResource(uv.${i}, "${i}");
|
|
2348
|
+
`);
|
|
2349
|
+
}
|
|
2350
|
+
continue;
|
|
2351
|
+
}
|
|
2352
|
+
const uniform = group.uniformStructures[i];
|
|
2353
|
+
let parsed = false;
|
|
2354
|
+
for (let j = 0; j < uniformParsers.length; j++) {
|
|
2355
|
+
const parser = uniformParsers[j];
|
|
2356
|
+
if (uniform.type === parser.type && parser.test(uniform)) {
|
|
2357
|
+
funcFragments.push(`name = "${i}";`, uniformParsers[j].uniform);
|
|
2358
|
+
parsed = true;
|
|
2359
|
+
break;
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
if (!parsed) {
|
|
2363
|
+
const templateType = uniform.size === 1 ? UNIFORM_TO_SINGLE_SETTERS : UNIFORM_TO_ARRAY_SETTERS;
|
|
2364
|
+
const template = templateType[uniform.type].replace("location", `ud["${i}"].location`);
|
|
2365
|
+
funcFragments.push(`
|
|
2366
|
+
cu = ud["${i}"];
|
|
2367
|
+
cv = cu.value;
|
|
2368
|
+
v = uv["${i}"];
|
|
2369
|
+
${template};`);
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
return new Function("ud", "uv", "renderer", "syncData", funcFragments.join("\n"));
|
|
2373
|
+
}
|
|
2374
|
+
class GlUniformGroupSystem {
|
|
2375
|
+
/** @param renderer - The renderer this System works for. */
|
|
2376
|
+
constructor(renderer) {
|
|
2377
|
+
this._cache = {};
|
|
2378
|
+
this._uniformGroupSyncHash = {};
|
|
2379
|
+
this._renderer = renderer;
|
|
2380
|
+
this.gl = null;
|
|
2381
|
+
this._cache = {};
|
|
2382
|
+
}
|
|
2383
|
+
contextChange(gl) {
|
|
2384
|
+
this.gl = gl;
|
|
2385
|
+
}
|
|
2386
|
+
/**
|
|
2387
|
+
* Uploads the uniforms values to the currently bound shader.
|
|
2388
|
+
* @param group - the uniforms values that be applied to the current shader
|
|
2389
|
+
* @param program
|
|
2390
|
+
* @param syncData
|
|
2391
|
+
* @param syncData.textureCount
|
|
2392
|
+
*/
|
|
2393
|
+
updateUniformGroup(group, program, syncData) {
|
|
2394
|
+
const programData = this._renderer.shader._getProgramData(program);
|
|
2395
|
+
if (!group.isStatic || group._dirtyId !== programData.uniformDirtyGroups[group.uid]) {
|
|
2396
|
+
programData.uniformDirtyGroups[group.uid] = group._dirtyId;
|
|
2397
|
+
const syncFunc = this._getUniformSyncFunction(group, program);
|
|
2398
|
+
syncFunc(programData.uniformData, group.uniforms, this._renderer, syncData);
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
/**
|
|
2402
|
+
* Overridable by the pixi.js/unsafe-eval package to use static syncUniforms instead.
|
|
2403
|
+
* @param group
|
|
2404
|
+
* @param program
|
|
2405
|
+
*/
|
|
2406
|
+
_getUniformSyncFunction(group, program) {
|
|
2407
|
+
return this._uniformGroupSyncHash[group._signature]?.[program._key] || this._createUniformSyncFunction(group, program);
|
|
2408
|
+
}
|
|
2409
|
+
_createUniformSyncFunction(group, program) {
|
|
2410
|
+
const uniformGroupSyncHash = this._uniformGroupSyncHash[group._signature] || (this._uniformGroupSyncHash[group._signature] = {});
|
|
2411
|
+
const id = this._getSignature(group, program._uniformData, "u");
|
|
2412
|
+
if (!this._cache[id]) {
|
|
2413
|
+
this._cache[id] = this._generateUniformsSync(group, program._uniformData);
|
|
2414
|
+
}
|
|
2415
|
+
uniformGroupSyncHash[program._key] = this._cache[id];
|
|
2416
|
+
return uniformGroupSyncHash[program._key];
|
|
2417
|
+
}
|
|
2418
|
+
_generateUniformsSync(group, uniformData) {
|
|
2419
|
+
return generateUniformsSync(group, uniformData);
|
|
2420
|
+
}
|
|
2421
|
+
/**
|
|
2422
|
+
* Takes a uniform group and data and generates a unique signature for them.
|
|
2423
|
+
* @param group - The uniform group to get signature of
|
|
2424
|
+
* @param group.uniforms
|
|
2425
|
+
* @param uniformData - Uniform information generated by the shader
|
|
2426
|
+
* @param preFix
|
|
2427
|
+
* @returns Unique signature of the uniform group
|
|
2428
|
+
*/
|
|
2429
|
+
_getSignature(group, uniformData, preFix) {
|
|
2430
|
+
const uniforms = group.uniforms;
|
|
2431
|
+
const strings = [`${preFix}-`];
|
|
2432
|
+
for (const i in uniforms) {
|
|
2433
|
+
strings.push(i);
|
|
2434
|
+
if (uniformData[i]) {
|
|
2435
|
+
strings.push(uniformData[i].type);
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
return strings.join("-");
|
|
2439
|
+
}
|
|
2440
|
+
/** Destroys this System and removes all its textures. */
|
|
2441
|
+
destroy() {
|
|
2442
|
+
this._renderer = null;
|
|
2443
|
+
this._cache = null;
|
|
2444
|
+
}
|
|
2445
|
+
}
|
|
2446
|
+
GlUniformGroupSystem.extension = {
|
|
2447
|
+
type: [
|
|
2448
|
+
ExtensionType.WebGLSystem
|
|
2449
|
+
],
|
|
2450
|
+
name: "uniformGroup"
|
|
2451
|
+
};
|
|
2452
|
+
function mapWebGLBlendModesToPixi(gl) {
|
|
2453
|
+
const blendMap = {};
|
|
2454
|
+
blendMap.normal = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
|
|
2455
|
+
blendMap.add = [gl.ONE, gl.ONE];
|
|
2456
|
+
blendMap.multiply = [gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
|
|
2457
|
+
blendMap.screen = [gl.ONE, gl.ONE_MINUS_SRC_COLOR, gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
|
|
2458
|
+
blendMap.none = [0, 0];
|
|
2459
|
+
blendMap["normal-npm"] = [gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
|
|
2460
|
+
blendMap["add-npm"] = [gl.SRC_ALPHA, gl.ONE, gl.ONE, gl.ONE];
|
|
2461
|
+
blendMap["screen-npm"] = [gl.SRC_ALPHA, gl.ONE_MINUS_SRC_COLOR, gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
|
|
2462
|
+
blendMap.erase = [gl.ZERO, gl.ONE_MINUS_SRC_ALPHA];
|
|
2463
|
+
const isWebGl2 = !(gl instanceof DOMAdapter.get().getWebGLRenderingContext());
|
|
2464
|
+
if (isWebGl2) {
|
|
2465
|
+
blendMap.min = [gl.ONE, gl.ONE, gl.ONE, gl.ONE, gl.MIN, gl.MIN];
|
|
2466
|
+
blendMap.max = [gl.ONE, gl.ONE, gl.ONE, gl.ONE, gl.MAX, gl.MAX];
|
|
2467
|
+
} else {
|
|
2468
|
+
const ext = gl.getExtension("EXT_blend_minmax");
|
|
2469
|
+
if (ext) {
|
|
2470
|
+
blendMap.min = [gl.ONE, gl.ONE, gl.ONE, gl.ONE, ext.MIN_EXT, ext.MIN_EXT];
|
|
2471
|
+
blendMap.max = [gl.ONE, gl.ONE, gl.ONE, gl.ONE, ext.MAX_EXT, ext.MAX_EXT];
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
return blendMap;
|
|
2475
|
+
}
|
|
2476
|
+
const BLEND = 0;
|
|
2477
|
+
const OFFSET = 1;
|
|
2478
|
+
const CULLING = 2;
|
|
2479
|
+
const DEPTH_TEST = 3;
|
|
2480
|
+
const WINDING = 4;
|
|
2481
|
+
const DEPTH_MASK = 5;
|
|
2482
|
+
const _GlStateSystem = class _GlStateSystem2 {
|
|
2483
|
+
constructor(renderer) {
|
|
2484
|
+
this._invertFrontFace = false;
|
|
2485
|
+
this.gl = null;
|
|
2486
|
+
this.stateId = 0;
|
|
2487
|
+
this.polygonOffset = 0;
|
|
2488
|
+
this.blendMode = "none";
|
|
2489
|
+
this._blendEq = false;
|
|
2490
|
+
this.map = [];
|
|
2491
|
+
this.map[BLEND] = this.setBlend;
|
|
2492
|
+
this.map[OFFSET] = this.setOffset;
|
|
2493
|
+
this.map[CULLING] = this.setCullFace;
|
|
2494
|
+
this.map[DEPTH_TEST] = this.setDepthTest;
|
|
2495
|
+
this.map[WINDING] = this.setFrontFace;
|
|
2496
|
+
this.map[DEPTH_MASK] = this.setDepthMask;
|
|
2497
|
+
this.checks = [];
|
|
2498
|
+
this.defaultState = State.for2d();
|
|
2499
|
+
renderer.renderTarget.onRenderTargetChange.add(this);
|
|
2500
|
+
}
|
|
2501
|
+
onRenderTargetChange(renderTarget) {
|
|
2502
|
+
this._invertFrontFace = !renderTarget.isRoot;
|
|
2503
|
+
if (this._cullFace) {
|
|
2504
|
+
this.setFrontFace(this._frontFace);
|
|
2505
|
+
} else {
|
|
2506
|
+
this._frontFaceDirty = true;
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
contextChange(gl) {
|
|
2510
|
+
this.gl = gl;
|
|
2511
|
+
this.blendModesMap = mapWebGLBlendModesToPixi(gl);
|
|
2512
|
+
this.resetState();
|
|
2513
|
+
}
|
|
2514
|
+
/**
|
|
2515
|
+
* Sets the current state
|
|
2516
|
+
* @param {*} state - The state to set.
|
|
2517
|
+
*/
|
|
2518
|
+
set(state) {
|
|
2519
|
+
state || (state = this.defaultState);
|
|
2520
|
+
if (this.stateId !== state.data) {
|
|
2521
|
+
let diff = this.stateId ^ state.data;
|
|
2522
|
+
let i = 0;
|
|
2523
|
+
while (diff) {
|
|
2524
|
+
if (diff & 1) {
|
|
2525
|
+
this.map[i].call(this, !!(state.data & 1 << i));
|
|
2526
|
+
}
|
|
2527
|
+
diff >>= 1;
|
|
2528
|
+
i++;
|
|
2529
|
+
}
|
|
2530
|
+
this.stateId = state.data;
|
|
2531
|
+
}
|
|
2532
|
+
for (let i = 0; i < this.checks.length; i++) {
|
|
2533
|
+
this.checks[i](this, state);
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
/**
|
|
2537
|
+
* Sets the state, when previous state is unknown.
|
|
2538
|
+
* @param {*} state - The state to set
|
|
2539
|
+
*/
|
|
2540
|
+
forceState(state) {
|
|
2541
|
+
state || (state = this.defaultState);
|
|
2542
|
+
for (let i = 0; i < this.map.length; i++) {
|
|
2543
|
+
this.map[i].call(this, !!(state.data & 1 << i));
|
|
2544
|
+
}
|
|
2545
|
+
for (let i = 0; i < this.checks.length; i++) {
|
|
2546
|
+
this.checks[i](this, state);
|
|
2547
|
+
}
|
|
2548
|
+
this.stateId = state.data;
|
|
2549
|
+
}
|
|
2550
|
+
/**
|
|
2551
|
+
* Sets whether to enable or disable blending.
|
|
2552
|
+
* @param value - Turn on or off WebGl blending.
|
|
2553
|
+
*/
|
|
2554
|
+
setBlend(value) {
|
|
2555
|
+
this._updateCheck(_GlStateSystem2._checkBlendMode, value);
|
|
2556
|
+
this.gl[value ? "enable" : "disable"](this.gl.BLEND);
|
|
2557
|
+
}
|
|
2558
|
+
/**
|
|
2559
|
+
* Sets whether to enable or disable polygon offset fill.
|
|
2560
|
+
* @param value - Turn on or off webgl polygon offset testing.
|
|
2561
|
+
*/
|
|
2562
|
+
setOffset(value) {
|
|
2563
|
+
this._updateCheck(_GlStateSystem2._checkPolygonOffset, value);
|
|
2564
|
+
this.gl[value ? "enable" : "disable"](this.gl.POLYGON_OFFSET_FILL);
|
|
2565
|
+
}
|
|
2566
|
+
/**
|
|
2567
|
+
* Sets whether to enable or disable depth test.
|
|
2568
|
+
* @param value - Turn on or off webgl depth testing.
|
|
2569
|
+
*/
|
|
2570
|
+
setDepthTest(value) {
|
|
2571
|
+
this.gl[value ? "enable" : "disable"](this.gl.DEPTH_TEST);
|
|
2572
|
+
}
|
|
2573
|
+
/**
|
|
2574
|
+
* Sets whether to enable or disable depth mask.
|
|
2575
|
+
* @param value - Turn on or off webgl depth mask.
|
|
2576
|
+
*/
|
|
2577
|
+
setDepthMask(value) {
|
|
2578
|
+
this.gl.depthMask(value);
|
|
2579
|
+
}
|
|
2580
|
+
/**
|
|
2581
|
+
* Sets whether to enable or disable cull face.
|
|
2582
|
+
* @param {boolean} value - Turn on or off webgl cull face.
|
|
2583
|
+
*/
|
|
2584
|
+
setCullFace(value) {
|
|
2585
|
+
this._cullFace = value;
|
|
2586
|
+
this.gl[value ? "enable" : "disable"](this.gl.CULL_FACE);
|
|
2587
|
+
if (this._cullFace && this._frontFaceDirty) {
|
|
2588
|
+
this.setFrontFace(this._frontFace);
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
/**
|
|
2592
|
+
* Sets the gl front face.
|
|
2593
|
+
* @param {boolean} value - true is clockwise and false is counter-clockwise
|
|
2594
|
+
*/
|
|
2595
|
+
setFrontFace(value) {
|
|
2596
|
+
this._frontFace = value;
|
|
2597
|
+
this._frontFaceDirty = false;
|
|
2598
|
+
const faceMode = this._invertFrontFace ? !value : value;
|
|
2599
|
+
if (this._glFrontFace !== faceMode) {
|
|
2600
|
+
this._glFrontFace = faceMode;
|
|
2601
|
+
this.gl.frontFace(this.gl[faceMode ? "CW" : "CCW"]);
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
/**
|
|
2605
|
+
* Sets the blend mode.
|
|
2606
|
+
* @param {number} value - The blend mode to set to.
|
|
2607
|
+
*/
|
|
2608
|
+
setBlendMode(value) {
|
|
2609
|
+
if (!this.blendModesMap[value]) {
|
|
2610
|
+
value = "normal";
|
|
2611
|
+
}
|
|
2612
|
+
if (value === this.blendMode) {
|
|
2613
|
+
return;
|
|
2614
|
+
}
|
|
2615
|
+
this.blendMode = value;
|
|
2616
|
+
const mode = this.blendModesMap[value];
|
|
2617
|
+
const gl = this.gl;
|
|
2618
|
+
if (mode.length === 2) {
|
|
2619
|
+
gl.blendFunc(mode[0], mode[1]);
|
|
2620
|
+
} else {
|
|
2621
|
+
gl.blendFuncSeparate(mode[0], mode[1], mode[2], mode[3]);
|
|
2622
|
+
}
|
|
2623
|
+
if (mode.length === 6) {
|
|
2624
|
+
this._blendEq = true;
|
|
2625
|
+
gl.blendEquationSeparate(mode[4], mode[5]);
|
|
2626
|
+
} else if (this._blendEq) {
|
|
2627
|
+
this._blendEq = false;
|
|
2628
|
+
gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
|
|
2629
|
+
}
|
|
2630
|
+
}
|
|
2631
|
+
/**
|
|
2632
|
+
* Sets the polygon offset.
|
|
2633
|
+
* @param {number} value - the polygon offset
|
|
2634
|
+
* @param {number} scale - the polygon offset scale
|
|
2635
|
+
*/
|
|
2636
|
+
setPolygonOffset(value, scale) {
|
|
2637
|
+
this.gl.polygonOffset(value, scale);
|
|
2638
|
+
}
|
|
2639
|
+
/** Resets all the logic and disables the VAOs. */
|
|
2640
|
+
resetState() {
|
|
2641
|
+
this._glFrontFace = false;
|
|
2642
|
+
this._frontFace = false;
|
|
2643
|
+
this._cullFace = false;
|
|
2644
|
+
this._frontFaceDirty = false;
|
|
2645
|
+
this._invertFrontFace = false;
|
|
2646
|
+
this.gl.frontFace(this.gl.CCW);
|
|
2647
|
+
this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false);
|
|
2648
|
+
this.forceState(this.defaultState);
|
|
2649
|
+
this._blendEq = true;
|
|
2650
|
+
this.blendMode = "";
|
|
2651
|
+
this.setBlendMode("normal");
|
|
2652
|
+
}
|
|
2653
|
+
/**
|
|
2654
|
+
* Checks to see which updates should be checked based on which settings have been activated.
|
|
2655
|
+
*
|
|
2656
|
+
* For example, if blend is enabled then we should check the blend modes each time the state is changed
|
|
2657
|
+
* or if polygon fill is activated then we need to check if the polygon offset changes.
|
|
2658
|
+
* The idea is that we only check what we have too.
|
|
2659
|
+
* @param func - the checking function to add or remove
|
|
2660
|
+
* @param value - should the check function be added or removed.
|
|
2661
|
+
*/
|
|
2662
|
+
_updateCheck(func, value) {
|
|
2663
|
+
const index = this.checks.indexOf(func);
|
|
2664
|
+
if (value && index === -1) {
|
|
2665
|
+
this.checks.push(func);
|
|
2666
|
+
} else if (!value && index !== -1) {
|
|
2667
|
+
this.checks.splice(index, 1);
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
/**
|
|
2671
|
+
* A private little wrapper function that we call to check the blend mode.
|
|
2672
|
+
* @param system - the System to perform the state check on
|
|
2673
|
+
* @param state - the state that the blendMode will pulled from
|
|
2674
|
+
*/
|
|
2675
|
+
static _checkBlendMode(system, state) {
|
|
2676
|
+
system.setBlendMode(state.blendMode);
|
|
2677
|
+
}
|
|
2678
|
+
/**
|
|
2679
|
+
* A private little wrapper function that we call to check the polygon offset.
|
|
2680
|
+
* @param system - the System to perform the state check on
|
|
2681
|
+
* @param state - the state that the blendMode will pulled from
|
|
2682
|
+
*/
|
|
2683
|
+
static _checkPolygonOffset(system, state) {
|
|
2684
|
+
system.setPolygonOffset(1, state.polygonOffset);
|
|
2685
|
+
}
|
|
2686
|
+
/** @ignore */
|
|
2687
|
+
destroy() {
|
|
2688
|
+
this.gl = null;
|
|
2689
|
+
this.checks.length = 0;
|
|
2690
|
+
}
|
|
2691
|
+
};
|
|
2692
|
+
_GlStateSystem.extension = {
|
|
2693
|
+
type: [
|
|
2694
|
+
ExtensionType.WebGLSystem
|
|
2695
|
+
],
|
|
2696
|
+
name: "state"
|
|
2697
|
+
};
|
|
2698
|
+
let GlStateSystem = _GlStateSystem;
|
|
2699
|
+
class GlTexture {
|
|
2700
|
+
constructor(texture) {
|
|
2701
|
+
this.target = GL_TARGETS.TEXTURE_2D;
|
|
2702
|
+
this._layerInitMask = 0;
|
|
2703
|
+
this.texture = texture;
|
|
2704
|
+
this.width = -1;
|
|
2705
|
+
this.height = -1;
|
|
2706
|
+
this.type = GL_TYPES.UNSIGNED_BYTE;
|
|
2707
|
+
this.internalFormat = GL_FORMATS.RGBA;
|
|
2708
|
+
this.format = GL_FORMATS.RGBA;
|
|
2709
|
+
this.samplerType = 0;
|
|
2710
|
+
}
|
|
2711
|
+
destroy() {
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2714
|
+
const glUploadBufferImageResource = {
|
|
2715
|
+
id: "buffer",
|
|
2716
|
+
upload(source, glTexture, gl, _webGLVersion, targetOverride, forceAllocation = false) {
|
|
2717
|
+
const target = targetOverride || glTexture.target;
|
|
2718
|
+
if (!forceAllocation && (glTexture.width === source.width && glTexture.height === source.height)) {
|
|
2719
|
+
gl.texSubImage2D(
|
|
2720
|
+
target,
|
|
2721
|
+
0,
|
|
2722
|
+
0,
|
|
2723
|
+
0,
|
|
2724
|
+
source.width,
|
|
2725
|
+
source.height,
|
|
2726
|
+
glTexture.format,
|
|
2727
|
+
glTexture.type,
|
|
2728
|
+
source.resource
|
|
2729
|
+
);
|
|
2730
|
+
} else {
|
|
2731
|
+
gl.texImage2D(
|
|
2732
|
+
target,
|
|
2733
|
+
0,
|
|
2734
|
+
glTexture.internalFormat,
|
|
2735
|
+
source.width,
|
|
2736
|
+
source.height,
|
|
2737
|
+
0,
|
|
2738
|
+
glTexture.format,
|
|
2739
|
+
glTexture.type,
|
|
2740
|
+
source.resource
|
|
2741
|
+
);
|
|
2742
|
+
}
|
|
2743
|
+
glTexture.width = source.width;
|
|
2744
|
+
glTexture.height = source.height;
|
|
2745
|
+
}
|
|
2746
|
+
};
|
|
2747
|
+
const compressedFormatMap = {
|
|
2748
|
+
"bc1-rgba-unorm": true,
|
|
2749
|
+
"bc1-rgba-unorm-srgb": true,
|
|
2750
|
+
"bc2-rgba-unorm": true,
|
|
2751
|
+
"bc2-rgba-unorm-srgb": true,
|
|
2752
|
+
"bc3-rgba-unorm": true,
|
|
2753
|
+
"bc3-rgba-unorm-srgb": true,
|
|
2754
|
+
"bc4-r-unorm": true,
|
|
2755
|
+
"bc4-r-snorm": true,
|
|
2756
|
+
"bc5-rg-unorm": true,
|
|
2757
|
+
"bc5-rg-snorm": true,
|
|
2758
|
+
"bc6h-rgb-ufloat": true,
|
|
2759
|
+
"bc6h-rgb-float": true,
|
|
2760
|
+
"bc7-rgba-unorm": true,
|
|
2761
|
+
"bc7-rgba-unorm-srgb": true,
|
|
2762
|
+
// ETC2 compressed formats usable if "texture-compression-etc2" is both
|
|
2763
|
+
// supported by the device/user agent and enabled in requestDevice.
|
|
2764
|
+
"etc2-rgb8unorm": true,
|
|
2765
|
+
"etc2-rgb8unorm-srgb": true,
|
|
2766
|
+
"etc2-rgb8a1unorm": true,
|
|
2767
|
+
"etc2-rgb8a1unorm-srgb": true,
|
|
2768
|
+
"etc2-rgba8unorm": true,
|
|
2769
|
+
"etc2-rgba8unorm-srgb": true,
|
|
2770
|
+
"eac-r11unorm": true,
|
|
2771
|
+
"eac-r11snorm": true,
|
|
2772
|
+
"eac-rg11unorm": true,
|
|
2773
|
+
"eac-rg11snorm": true,
|
|
2774
|
+
// ASTC compressed formats usable if "texture-compression-astc" is both
|
|
2775
|
+
// supported by the device/user agent and enabled in requestDevice.
|
|
2776
|
+
"astc-4x4-unorm": true,
|
|
2777
|
+
"astc-4x4-unorm-srgb": true,
|
|
2778
|
+
"astc-5x4-unorm": true,
|
|
2779
|
+
"astc-5x4-unorm-srgb": true,
|
|
2780
|
+
"astc-5x5-unorm": true,
|
|
2781
|
+
"astc-5x5-unorm-srgb": true,
|
|
2782
|
+
"astc-6x5-unorm": true,
|
|
2783
|
+
"astc-6x5-unorm-srgb": true,
|
|
2784
|
+
"astc-6x6-unorm": true,
|
|
2785
|
+
"astc-6x6-unorm-srgb": true,
|
|
2786
|
+
"astc-8x5-unorm": true,
|
|
2787
|
+
"astc-8x5-unorm-srgb": true,
|
|
2788
|
+
"astc-8x6-unorm": true,
|
|
2789
|
+
"astc-8x6-unorm-srgb": true,
|
|
2790
|
+
"astc-8x8-unorm": true,
|
|
2791
|
+
"astc-8x8-unorm-srgb": true,
|
|
2792
|
+
"astc-10x5-unorm": true,
|
|
2793
|
+
"astc-10x5-unorm-srgb": true,
|
|
2794
|
+
"astc-10x6-unorm": true,
|
|
2795
|
+
"astc-10x6-unorm-srgb": true,
|
|
2796
|
+
"astc-10x8-unorm": true,
|
|
2797
|
+
"astc-10x8-unorm-srgb": true,
|
|
2798
|
+
"astc-10x10-unorm": true,
|
|
2799
|
+
"astc-10x10-unorm-srgb": true,
|
|
2800
|
+
"astc-12x10-unorm": true,
|
|
2801
|
+
"astc-12x10-unorm-srgb": true,
|
|
2802
|
+
"astc-12x12-unorm": true,
|
|
2803
|
+
"astc-12x12-unorm-srgb": true
|
|
2804
|
+
};
|
|
2805
|
+
const glUploadCompressedTextureResource = {
|
|
2806
|
+
id: "compressed",
|
|
2807
|
+
upload(source, glTexture, gl, _webGLVersion, targetOverride, _forceAllocation) {
|
|
2808
|
+
const target = targetOverride ?? glTexture.target;
|
|
2809
|
+
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
|
|
2810
|
+
let mipWidth = source.pixelWidth;
|
|
2811
|
+
let mipHeight = source.pixelHeight;
|
|
2812
|
+
const compressed = !!compressedFormatMap[source.format];
|
|
2813
|
+
for (let i = 0; i < source.resource.length; i++) {
|
|
2814
|
+
const levelBuffer = source.resource[i];
|
|
2815
|
+
if (compressed) {
|
|
2816
|
+
gl.compressedTexImage2D(
|
|
2817
|
+
target,
|
|
2818
|
+
i,
|
|
2819
|
+
glTexture.internalFormat,
|
|
2820
|
+
mipWidth,
|
|
2821
|
+
mipHeight,
|
|
2822
|
+
0,
|
|
2823
|
+
levelBuffer
|
|
2824
|
+
);
|
|
2825
|
+
} else {
|
|
2826
|
+
gl.texImage2D(
|
|
2827
|
+
target,
|
|
2828
|
+
i,
|
|
2829
|
+
glTexture.internalFormat,
|
|
2830
|
+
mipWidth,
|
|
2831
|
+
mipHeight,
|
|
2832
|
+
0,
|
|
2833
|
+
glTexture.format,
|
|
2834
|
+
glTexture.type,
|
|
2835
|
+
levelBuffer
|
|
2836
|
+
);
|
|
2837
|
+
}
|
|
2838
|
+
mipWidth = Math.max(mipWidth >> 1, 1);
|
|
2839
|
+
mipHeight = Math.max(mipHeight >> 1, 1);
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
};
|
|
2843
|
+
const FACE_ORDER = ["right", "left", "top", "bottom", "front", "back"];
|
|
2844
|
+
function createGlUploadCubeTextureResource(uploaders) {
|
|
2845
|
+
return {
|
|
2846
|
+
id: "cube",
|
|
2847
|
+
upload(source, glTexture, gl, webGLVersion) {
|
|
2848
|
+
const faces = source.faces;
|
|
2849
|
+
for (let faceIndex = 0; faceIndex < FACE_ORDER.length; faceIndex++) {
|
|
2850
|
+
const key = FACE_ORDER[faceIndex];
|
|
2851
|
+
const face = faces[key];
|
|
2852
|
+
const uploader = uploaders[face.uploadMethodId] || uploaders.image;
|
|
2853
|
+
uploader.upload(
|
|
2854
|
+
face,
|
|
2855
|
+
glTexture,
|
|
2856
|
+
gl,
|
|
2857
|
+
webGLVersion,
|
|
2858
|
+
// Use the face target for the current face. cube faces ids go up 1 so
|
|
2859
|
+
// GL_TARGETS.TEXTURE_CUBE_MAP_POSITIVE_X + i addresses the i'th face target.
|
|
2860
|
+
GL_TARGETS.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex,
|
|
2861
|
+
// Force allocation for the first upload of each face.
|
|
2862
|
+
(glTexture._layerInitMask & 1 << faceIndex) === 0
|
|
2863
|
+
);
|
|
2864
|
+
glTexture._layerInitMask |= 1 << faceIndex;
|
|
2865
|
+
}
|
|
2866
|
+
glTexture.width = source.pixelWidth;
|
|
2867
|
+
glTexture.height = source.pixelHeight;
|
|
2868
|
+
}
|
|
2869
|
+
};
|
|
2870
|
+
}
|
|
2871
|
+
const glUploadImageResource = {
|
|
2872
|
+
id: "image",
|
|
2873
|
+
upload(source, glTexture, gl, webGLVersion, targetOverride, forceAllocation = false) {
|
|
2874
|
+
const target = targetOverride || glTexture.target;
|
|
2875
|
+
const textureWidth = source.pixelWidth;
|
|
2876
|
+
const textureHeight = source.pixelHeight;
|
|
2877
|
+
const resourceWidth = source.resourceWidth;
|
|
2878
|
+
const resourceHeight = source.resourceHeight;
|
|
2879
|
+
const isWebGL2 = webGLVersion === 2;
|
|
2880
|
+
const needsAllocation = forceAllocation || glTexture.width !== textureWidth || glTexture.height !== textureHeight;
|
|
2881
|
+
const resourceFitsTexture = resourceWidth >= textureWidth && resourceHeight >= textureHeight;
|
|
2882
|
+
const resource = source.resource;
|
|
2883
|
+
const uploadFunction = isWebGL2 ? uploadImageWebGL2 : uploadImageWebGL1;
|
|
2884
|
+
uploadFunction(
|
|
2885
|
+
gl,
|
|
2886
|
+
target,
|
|
2887
|
+
glTexture,
|
|
2888
|
+
textureWidth,
|
|
2889
|
+
textureHeight,
|
|
2890
|
+
resourceWidth,
|
|
2891
|
+
resourceHeight,
|
|
2892
|
+
resource,
|
|
2893
|
+
needsAllocation,
|
|
2894
|
+
resourceFitsTexture
|
|
2895
|
+
);
|
|
2896
|
+
glTexture.width = textureWidth;
|
|
2897
|
+
glTexture.height = textureHeight;
|
|
2898
|
+
}
|
|
2899
|
+
};
|
|
2900
|
+
function uploadImageWebGL2(gl, target, glTexture, textureWidth, textureHeight, resourceWidth, resourceHeight, resource, needsAllocation, resourceFitsTexture) {
|
|
2901
|
+
if (!resourceFitsTexture) {
|
|
2902
|
+
if (needsAllocation) {
|
|
2903
|
+
gl.texImage2D(
|
|
2904
|
+
target,
|
|
2905
|
+
0,
|
|
2906
|
+
glTexture.internalFormat,
|
|
2907
|
+
textureWidth,
|
|
2908
|
+
textureHeight,
|
|
2909
|
+
0,
|
|
2910
|
+
glTexture.format,
|
|
2911
|
+
glTexture.type,
|
|
2912
|
+
null
|
|
2913
|
+
);
|
|
2914
|
+
}
|
|
2915
|
+
gl.texSubImage2D(
|
|
2916
|
+
target,
|
|
2917
|
+
0,
|
|
2918
|
+
0,
|
|
2919
|
+
0,
|
|
2920
|
+
resourceWidth,
|
|
2921
|
+
resourceHeight,
|
|
2922
|
+
glTexture.format,
|
|
2923
|
+
glTexture.type,
|
|
2924
|
+
resource
|
|
2925
|
+
);
|
|
2926
|
+
return;
|
|
2927
|
+
}
|
|
2928
|
+
if (!needsAllocation) {
|
|
2929
|
+
gl.texSubImage2D(
|
|
2930
|
+
target,
|
|
2931
|
+
0,
|
|
2932
|
+
0,
|
|
2933
|
+
0,
|
|
2934
|
+
glTexture.format,
|
|
2935
|
+
glTexture.type,
|
|
2936
|
+
resource
|
|
2937
|
+
);
|
|
2938
|
+
return;
|
|
2939
|
+
}
|
|
2940
|
+
gl.texImage2D(
|
|
2941
|
+
target,
|
|
2942
|
+
0,
|
|
2943
|
+
glTexture.internalFormat,
|
|
2944
|
+
textureWidth,
|
|
2945
|
+
textureHeight,
|
|
2946
|
+
0,
|
|
2947
|
+
glTexture.format,
|
|
2948
|
+
glTexture.type,
|
|
2949
|
+
resource
|
|
2950
|
+
);
|
|
2951
|
+
}
|
|
2952
|
+
function uploadImageWebGL1(gl, target, glTexture, textureWidth, textureHeight, _resourceWidth, _resourceHeight, resource, needsAllocation, resourceFitsTexture) {
|
|
2953
|
+
if (!resourceFitsTexture) {
|
|
2954
|
+
if (needsAllocation) {
|
|
2955
|
+
gl.texImage2D(
|
|
2956
|
+
target,
|
|
2957
|
+
0,
|
|
2958
|
+
glTexture.internalFormat,
|
|
2959
|
+
textureWidth,
|
|
2960
|
+
textureHeight,
|
|
2961
|
+
0,
|
|
2962
|
+
glTexture.format,
|
|
2963
|
+
glTexture.type,
|
|
2964
|
+
null
|
|
2965
|
+
);
|
|
2966
|
+
}
|
|
2967
|
+
gl.texSubImage2D(
|
|
2968
|
+
target,
|
|
2969
|
+
0,
|
|
2970
|
+
0,
|
|
2971
|
+
0,
|
|
2972
|
+
glTexture.format,
|
|
2973
|
+
glTexture.type,
|
|
2974
|
+
resource
|
|
2975
|
+
);
|
|
2976
|
+
return;
|
|
2977
|
+
}
|
|
2978
|
+
if (!needsAllocation) {
|
|
2979
|
+
gl.texSubImage2D(
|
|
2980
|
+
target,
|
|
2981
|
+
0,
|
|
2982
|
+
0,
|
|
2983
|
+
0,
|
|
2984
|
+
glTexture.format,
|
|
2985
|
+
glTexture.type,
|
|
2986
|
+
resource
|
|
2987
|
+
);
|
|
2988
|
+
return;
|
|
2989
|
+
}
|
|
2990
|
+
gl.texImage2D(
|
|
2991
|
+
target,
|
|
2992
|
+
0,
|
|
2993
|
+
glTexture.internalFormat,
|
|
2994
|
+
glTexture.format,
|
|
2995
|
+
glTexture.type,
|
|
2996
|
+
resource
|
|
2997
|
+
);
|
|
2998
|
+
}
|
|
2999
|
+
const defaultForceAllocation = isSafari();
|
|
3000
|
+
const glUploadVideoResource = {
|
|
3001
|
+
id: "video",
|
|
3002
|
+
upload(source, glTexture, gl, webGLVersion, targetOverride, forceAllocation = defaultForceAllocation) {
|
|
3003
|
+
if (!source.isValid) {
|
|
3004
|
+
const target = targetOverride ?? glTexture.target;
|
|
3005
|
+
gl.texImage2D(
|
|
3006
|
+
target,
|
|
3007
|
+
0,
|
|
3008
|
+
glTexture.internalFormat,
|
|
3009
|
+
1,
|
|
3010
|
+
1,
|
|
3011
|
+
0,
|
|
3012
|
+
glTexture.format,
|
|
3013
|
+
glTexture.type,
|
|
3014
|
+
null
|
|
3015
|
+
);
|
|
3016
|
+
return;
|
|
3017
|
+
}
|
|
3018
|
+
glUploadImageResource.upload(source, glTexture, gl, webGLVersion, targetOverride, forceAllocation);
|
|
3019
|
+
}
|
|
3020
|
+
};
|
|
3021
|
+
const scaleModeToGlFilter = {
|
|
3022
|
+
linear: 9729,
|
|
3023
|
+
nearest: 9728
|
|
3024
|
+
};
|
|
3025
|
+
const mipmapScaleModeToGlFilter = {
|
|
3026
|
+
linear: {
|
|
3027
|
+
linear: 9987,
|
|
3028
|
+
nearest: 9985
|
|
3029
|
+
},
|
|
3030
|
+
nearest: {
|
|
3031
|
+
linear: 9986,
|
|
3032
|
+
nearest: 9984
|
|
3033
|
+
}
|
|
3034
|
+
};
|
|
3035
|
+
const wrapModeToGlAddress = {
|
|
3036
|
+
"clamp-to-edge": 33071,
|
|
3037
|
+
repeat: 10497,
|
|
3038
|
+
"mirror-repeat": 33648
|
|
3039
|
+
};
|
|
3040
|
+
const compareModeToGlCompare = {
|
|
3041
|
+
never: 512,
|
|
3042
|
+
less: 513,
|
|
3043
|
+
equal: 514,
|
|
3044
|
+
"less-equal": 515,
|
|
3045
|
+
greater: 516,
|
|
3046
|
+
"not-equal": 517,
|
|
3047
|
+
"greater-equal": 518,
|
|
3048
|
+
always: 519
|
|
3049
|
+
};
|
|
3050
|
+
function applyStyleParams(style, gl, mipmaps, anisotropicExt, glFunctionName, firstParam, forceClamp, firstCreation) {
|
|
3051
|
+
const castParam = firstParam;
|
|
3052
|
+
if (!firstCreation || style.addressModeU !== "repeat" || style.addressModeV !== "repeat" || style.addressModeW !== "repeat") {
|
|
3053
|
+
const wrapModeS = wrapModeToGlAddress[forceClamp ? "clamp-to-edge" : style.addressModeU];
|
|
3054
|
+
const wrapModeT = wrapModeToGlAddress[forceClamp ? "clamp-to-edge" : style.addressModeV];
|
|
3055
|
+
const wrapModeR = wrapModeToGlAddress[forceClamp ? "clamp-to-edge" : style.addressModeW];
|
|
3056
|
+
gl[glFunctionName](castParam, gl.TEXTURE_WRAP_S, wrapModeS);
|
|
3057
|
+
gl[glFunctionName](castParam, gl.TEXTURE_WRAP_T, wrapModeT);
|
|
3058
|
+
if (gl.TEXTURE_WRAP_R) gl[glFunctionName](castParam, gl.TEXTURE_WRAP_R, wrapModeR);
|
|
3059
|
+
}
|
|
3060
|
+
if (!firstCreation || style.magFilter !== "linear") {
|
|
3061
|
+
gl[glFunctionName](castParam, gl.TEXTURE_MAG_FILTER, scaleModeToGlFilter[style.magFilter]);
|
|
3062
|
+
}
|
|
3063
|
+
if (mipmaps) {
|
|
3064
|
+
if (!firstCreation || style.mipmapFilter !== "linear") {
|
|
3065
|
+
const glFilterMode = mipmapScaleModeToGlFilter[style.minFilter][style.mipmapFilter];
|
|
3066
|
+
gl[glFunctionName](castParam, gl.TEXTURE_MIN_FILTER, glFilterMode);
|
|
3067
|
+
}
|
|
3068
|
+
} else {
|
|
3069
|
+
gl[glFunctionName](castParam, gl.TEXTURE_MIN_FILTER, scaleModeToGlFilter[style.minFilter]);
|
|
3070
|
+
}
|
|
3071
|
+
if (anisotropicExt && style.maxAnisotropy > 1) {
|
|
3072
|
+
const level = Math.min(style.maxAnisotropy, gl.getParameter(anisotropicExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT));
|
|
3073
|
+
gl[glFunctionName](castParam, anisotropicExt.TEXTURE_MAX_ANISOTROPY_EXT, level);
|
|
3074
|
+
}
|
|
3075
|
+
if (style.compare) {
|
|
3076
|
+
gl[glFunctionName](castParam, gl.TEXTURE_COMPARE_FUNC, compareModeToGlCompare[style.compare]);
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3079
|
+
function mapFormatToGlFormat(gl) {
|
|
3080
|
+
return {
|
|
3081
|
+
// 8-bit formats
|
|
3082
|
+
r8unorm: gl.RED,
|
|
3083
|
+
r8snorm: gl.RED,
|
|
3084
|
+
r8uint: gl.RED,
|
|
3085
|
+
r8sint: gl.RED,
|
|
3086
|
+
// 16-bit formats
|
|
3087
|
+
r16uint: gl.RED,
|
|
3088
|
+
r16sint: gl.RED,
|
|
3089
|
+
r16float: gl.RED,
|
|
3090
|
+
rg8unorm: gl.RG,
|
|
3091
|
+
rg8snorm: gl.RG,
|
|
3092
|
+
rg8uint: gl.RG,
|
|
3093
|
+
rg8sint: gl.RG,
|
|
3094
|
+
// 32-bit formats
|
|
3095
|
+
r32uint: gl.RED,
|
|
3096
|
+
r32sint: gl.RED,
|
|
3097
|
+
r32float: gl.RED,
|
|
3098
|
+
rg16uint: gl.RG,
|
|
3099
|
+
rg16sint: gl.RG,
|
|
3100
|
+
rg16float: gl.RG,
|
|
3101
|
+
rgba8unorm: gl.RGBA,
|
|
3102
|
+
"rgba8unorm-srgb": gl.RGBA,
|
|
3103
|
+
// Packed 32-bit formats
|
|
3104
|
+
rgba8snorm: gl.RGBA,
|
|
3105
|
+
rgba8uint: gl.RGBA,
|
|
3106
|
+
rgba8sint: gl.RGBA,
|
|
3107
|
+
bgra8unorm: gl.RGBA,
|
|
3108
|
+
"bgra8unorm-srgb": gl.RGBA,
|
|
3109
|
+
rgb9e5ufloat: gl.RGB,
|
|
3110
|
+
rgb10a2unorm: gl.RGBA,
|
|
3111
|
+
rg11b10ufloat: gl.RGB,
|
|
3112
|
+
// 64-bit formats
|
|
3113
|
+
rg32uint: gl.RG,
|
|
3114
|
+
rg32sint: gl.RG,
|
|
3115
|
+
rg32float: gl.RG,
|
|
3116
|
+
rgba16uint: gl.RGBA,
|
|
3117
|
+
rgba16sint: gl.RGBA,
|
|
3118
|
+
rgba16float: gl.RGBA,
|
|
3119
|
+
// 128-bit formats
|
|
3120
|
+
rgba32uint: gl.RGBA,
|
|
3121
|
+
rgba32sint: gl.RGBA,
|
|
3122
|
+
rgba32float: gl.RGBA,
|
|
3123
|
+
// Depth/stencil formats
|
|
3124
|
+
stencil8: gl.STENCIL_INDEX8,
|
|
3125
|
+
depth16unorm: gl.DEPTH_COMPONENT,
|
|
3126
|
+
depth24plus: gl.DEPTH_COMPONENT,
|
|
3127
|
+
"depth24plus-stencil8": gl.DEPTH_STENCIL,
|
|
3128
|
+
depth32float: gl.DEPTH_COMPONENT,
|
|
3129
|
+
"depth32float-stencil8": gl.DEPTH_STENCIL
|
|
3130
|
+
};
|
|
3131
|
+
}
|
|
3132
|
+
function mapFormatToGlInternalFormat(gl, extensions2) {
|
|
3133
|
+
let srgb = {};
|
|
3134
|
+
let bgra8unorm = gl.RGBA;
|
|
3135
|
+
if (!(gl instanceof DOMAdapter.get().getWebGLRenderingContext())) {
|
|
3136
|
+
srgb = {
|
|
3137
|
+
"rgba8unorm-srgb": gl.SRGB8_ALPHA8,
|
|
3138
|
+
"bgra8unorm-srgb": gl.SRGB8_ALPHA8
|
|
3139
|
+
};
|
|
3140
|
+
bgra8unorm = gl.RGBA8;
|
|
3141
|
+
} else if (extensions2.srgb) {
|
|
3142
|
+
srgb = {
|
|
3143
|
+
"rgba8unorm-srgb": extensions2.srgb.SRGB8_ALPHA8_EXT,
|
|
3144
|
+
"bgra8unorm-srgb": extensions2.srgb.SRGB8_ALPHA8_EXT
|
|
3145
|
+
};
|
|
3146
|
+
}
|
|
3147
|
+
return {
|
|
3148
|
+
// 8-bit formats
|
|
3149
|
+
r8unorm: gl.R8,
|
|
3150
|
+
r8snorm: gl.R8_SNORM,
|
|
3151
|
+
r8uint: gl.R8UI,
|
|
3152
|
+
r8sint: gl.R8I,
|
|
3153
|
+
// 16-bit formats
|
|
3154
|
+
r16uint: gl.R16UI,
|
|
3155
|
+
r16sint: gl.R16I,
|
|
3156
|
+
r16float: gl.R16F,
|
|
3157
|
+
rg8unorm: gl.RG8,
|
|
3158
|
+
rg8snorm: gl.RG8_SNORM,
|
|
3159
|
+
rg8uint: gl.RG8UI,
|
|
3160
|
+
rg8sint: gl.RG8I,
|
|
3161
|
+
// 32-bit formats
|
|
3162
|
+
r32uint: gl.R32UI,
|
|
3163
|
+
r32sint: gl.R32I,
|
|
3164
|
+
r32float: gl.R32F,
|
|
3165
|
+
rg16uint: gl.RG16UI,
|
|
3166
|
+
rg16sint: gl.RG16I,
|
|
3167
|
+
rg16float: gl.RG16F,
|
|
3168
|
+
rgba8unorm: gl.RGBA,
|
|
3169
|
+
...srgb,
|
|
3170
|
+
// Packed 32-bit formats
|
|
3171
|
+
rgba8snorm: gl.RGBA8_SNORM,
|
|
3172
|
+
rgba8uint: gl.RGBA8UI,
|
|
3173
|
+
rgba8sint: gl.RGBA8I,
|
|
3174
|
+
bgra8unorm,
|
|
3175
|
+
rgb9e5ufloat: gl.RGB9_E5,
|
|
3176
|
+
rgb10a2unorm: gl.RGB10_A2,
|
|
3177
|
+
rg11b10ufloat: gl.R11F_G11F_B10F,
|
|
3178
|
+
// 64-bit formats
|
|
3179
|
+
rg32uint: gl.RG32UI,
|
|
3180
|
+
rg32sint: gl.RG32I,
|
|
3181
|
+
rg32float: gl.RG32F,
|
|
3182
|
+
rgba16uint: gl.RGBA16UI,
|
|
3183
|
+
rgba16sint: gl.RGBA16I,
|
|
3184
|
+
rgba16float: gl.RGBA16F,
|
|
3185
|
+
// 128-bit formats
|
|
3186
|
+
rgba32uint: gl.RGBA32UI,
|
|
3187
|
+
rgba32sint: gl.RGBA32I,
|
|
3188
|
+
rgba32float: gl.RGBA32F,
|
|
3189
|
+
// Depth/stencil formats
|
|
3190
|
+
stencil8: gl.STENCIL_INDEX8,
|
|
3191
|
+
depth16unorm: gl.DEPTH_COMPONENT16,
|
|
3192
|
+
depth24plus: gl.DEPTH_COMPONENT24,
|
|
3193
|
+
"depth24plus-stencil8": gl.DEPTH24_STENCIL8,
|
|
3194
|
+
depth32float: gl.DEPTH_COMPONENT32F,
|
|
3195
|
+
"depth32float-stencil8": gl.DEPTH32F_STENCIL8,
|
|
3196
|
+
// Compressed formats
|
|
3197
|
+
...extensions2.s3tc ? {
|
|
3198
|
+
"bc1-rgba-unorm": extensions2.s3tc.COMPRESSED_RGBA_S3TC_DXT1_EXT,
|
|
3199
|
+
"bc2-rgba-unorm": extensions2.s3tc.COMPRESSED_RGBA_S3TC_DXT3_EXT,
|
|
3200
|
+
"bc3-rgba-unorm": extensions2.s3tc.COMPRESSED_RGBA_S3TC_DXT5_EXT
|
|
3201
|
+
} : {},
|
|
3202
|
+
...extensions2.s3tc_sRGB ? {
|
|
3203
|
+
"bc1-rgba-unorm-srgb": extensions2.s3tc_sRGB.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
|
|
3204
|
+
"bc2-rgba-unorm-srgb": extensions2.s3tc_sRGB.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
|
|
3205
|
+
"bc3-rgba-unorm-srgb": extensions2.s3tc_sRGB.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
|
|
3206
|
+
} : {},
|
|
3207
|
+
...extensions2.rgtc ? {
|
|
3208
|
+
"bc4-r-unorm": extensions2.rgtc.COMPRESSED_RED_RGTC1_EXT,
|
|
3209
|
+
"bc4-r-snorm": extensions2.rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT,
|
|
3210
|
+
"bc5-rg-unorm": extensions2.rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT,
|
|
3211
|
+
"bc5-rg-snorm": extensions2.rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT
|
|
3212
|
+
} : {},
|
|
3213
|
+
...extensions2.bptc ? {
|
|
3214
|
+
"bc6h-rgb-float": extensions2.bptc.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT,
|
|
3215
|
+
"bc6h-rgb-ufloat": extensions2.bptc.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT,
|
|
3216
|
+
"bc7-rgba-unorm": extensions2.bptc.COMPRESSED_RGBA_BPTC_UNORM_EXT,
|
|
3217
|
+
"bc7-rgba-unorm-srgb": extensions2.bptc.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT
|
|
3218
|
+
} : {},
|
|
3219
|
+
...extensions2.etc ? {
|
|
3220
|
+
"etc2-rgb8unorm": extensions2.etc.COMPRESSED_RGB8_ETC2,
|
|
3221
|
+
"etc2-rgb8unorm-srgb": extensions2.etc.COMPRESSED_SRGB8_ETC2,
|
|
3222
|
+
"etc2-rgb8a1unorm": extensions2.etc.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
|
|
3223
|
+
"etc2-rgb8a1unorm-srgb": extensions2.etc.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
|
|
3224
|
+
"etc2-rgba8unorm": extensions2.etc.COMPRESSED_RGBA8_ETC2_EAC,
|
|
3225
|
+
"etc2-rgba8unorm-srgb": extensions2.etc.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
|
|
3226
|
+
"eac-r11unorm": extensions2.etc.COMPRESSED_R11_EAC,
|
|
3227
|
+
// 'eac-r11snorm'
|
|
3228
|
+
"eac-rg11unorm": extensions2.etc.COMPRESSED_SIGNED_RG11_EAC
|
|
3229
|
+
// 'eac-rg11snorm'
|
|
3230
|
+
} : {},
|
|
3231
|
+
...extensions2.astc ? {
|
|
3232
|
+
"astc-4x4-unorm": extensions2.astc.COMPRESSED_RGBA_ASTC_4x4_KHR,
|
|
3233
|
+
"astc-4x4-unorm-srgb": extensions2.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR,
|
|
3234
|
+
"astc-5x4-unorm": extensions2.astc.COMPRESSED_RGBA_ASTC_5x4_KHR,
|
|
3235
|
+
"astc-5x4-unorm-srgb": extensions2.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
|
|
3236
|
+
"astc-5x5-unorm": extensions2.astc.COMPRESSED_RGBA_ASTC_5x5_KHR,
|
|
3237
|
+
"astc-5x5-unorm-srgb": extensions2.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR,
|
|
3238
|
+
"astc-6x5-unorm": extensions2.astc.COMPRESSED_RGBA_ASTC_6x5_KHR,
|
|
3239
|
+
"astc-6x5-unorm-srgb": extensions2.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
|
|
3240
|
+
"astc-6x6-unorm": extensions2.astc.COMPRESSED_RGBA_ASTC_6x6_KHR,
|
|
3241
|
+
"astc-6x6-unorm-srgb": extensions2.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR,
|
|
3242
|
+
"astc-8x5-unorm": extensions2.astc.COMPRESSED_RGBA_ASTC_8x5_KHR,
|
|
3243
|
+
"astc-8x5-unorm-srgb": extensions2.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
|
|
3244
|
+
"astc-8x6-unorm": extensions2.astc.COMPRESSED_RGBA_ASTC_8x6_KHR,
|
|
3245
|
+
"astc-8x6-unorm-srgb": extensions2.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR,
|
|
3246
|
+
"astc-8x8-unorm": extensions2.astc.COMPRESSED_RGBA_ASTC_8x8_KHR,
|
|
3247
|
+
"astc-8x8-unorm-srgb": extensions2.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
|
|
3248
|
+
"astc-10x5-unorm": extensions2.astc.COMPRESSED_RGBA_ASTC_10x5_KHR,
|
|
3249
|
+
"astc-10x5-unorm-srgb": extensions2.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR,
|
|
3250
|
+
"astc-10x6-unorm": extensions2.astc.COMPRESSED_RGBA_ASTC_10x6_KHR,
|
|
3251
|
+
"astc-10x6-unorm-srgb": extensions2.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
|
|
3252
|
+
"astc-10x8-unorm": extensions2.astc.COMPRESSED_RGBA_ASTC_10x8_KHR,
|
|
3253
|
+
"astc-10x8-unorm-srgb": extensions2.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR,
|
|
3254
|
+
"astc-10x10-unorm": extensions2.astc.COMPRESSED_RGBA_ASTC_10x10_KHR,
|
|
3255
|
+
"astc-10x10-unorm-srgb": extensions2.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
|
|
3256
|
+
"astc-12x10-unorm": extensions2.astc.COMPRESSED_RGBA_ASTC_12x10_KHR,
|
|
3257
|
+
"astc-12x10-unorm-srgb": extensions2.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR,
|
|
3258
|
+
"astc-12x12-unorm": extensions2.astc.COMPRESSED_RGBA_ASTC_12x12_KHR,
|
|
3259
|
+
"astc-12x12-unorm-srgb": extensions2.astc.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
|
|
3260
|
+
} : {}
|
|
3261
|
+
};
|
|
3262
|
+
}
|
|
3263
|
+
function mapFormatToGlType(gl) {
|
|
3264
|
+
return {
|
|
3265
|
+
// 8-bit formats
|
|
3266
|
+
r8unorm: gl.UNSIGNED_BYTE,
|
|
3267
|
+
r8snorm: gl.BYTE,
|
|
3268
|
+
r8uint: gl.UNSIGNED_BYTE,
|
|
3269
|
+
r8sint: gl.BYTE,
|
|
3270
|
+
// 16-bit formats
|
|
3271
|
+
r16uint: gl.UNSIGNED_SHORT,
|
|
3272
|
+
r16sint: gl.SHORT,
|
|
3273
|
+
r16float: gl.HALF_FLOAT,
|
|
3274
|
+
rg8unorm: gl.UNSIGNED_BYTE,
|
|
3275
|
+
rg8snorm: gl.BYTE,
|
|
3276
|
+
rg8uint: gl.UNSIGNED_BYTE,
|
|
3277
|
+
rg8sint: gl.BYTE,
|
|
3278
|
+
// 32-bit formats
|
|
3279
|
+
r32uint: gl.UNSIGNED_INT,
|
|
3280
|
+
r32sint: gl.INT,
|
|
3281
|
+
r32float: gl.FLOAT,
|
|
3282
|
+
rg16uint: gl.UNSIGNED_SHORT,
|
|
3283
|
+
rg16sint: gl.SHORT,
|
|
3284
|
+
rg16float: gl.HALF_FLOAT,
|
|
3285
|
+
rgba8unorm: gl.UNSIGNED_BYTE,
|
|
3286
|
+
"rgba8unorm-srgb": gl.UNSIGNED_BYTE,
|
|
3287
|
+
// Packed 32-bit formats
|
|
3288
|
+
rgba8snorm: gl.BYTE,
|
|
3289
|
+
rgba8uint: gl.UNSIGNED_BYTE,
|
|
3290
|
+
rgba8sint: gl.BYTE,
|
|
3291
|
+
bgra8unorm: gl.UNSIGNED_BYTE,
|
|
3292
|
+
"bgra8unorm-srgb": gl.UNSIGNED_BYTE,
|
|
3293
|
+
rgb9e5ufloat: gl.UNSIGNED_INT_5_9_9_9_REV,
|
|
3294
|
+
rgb10a2unorm: gl.UNSIGNED_INT_2_10_10_10_REV,
|
|
3295
|
+
rg11b10ufloat: gl.UNSIGNED_INT_10F_11F_11F_REV,
|
|
3296
|
+
// 64-bit formats
|
|
3297
|
+
rg32uint: gl.UNSIGNED_INT,
|
|
3298
|
+
rg32sint: gl.INT,
|
|
3299
|
+
rg32float: gl.FLOAT,
|
|
3300
|
+
rgba16uint: gl.UNSIGNED_SHORT,
|
|
3301
|
+
rgba16sint: gl.SHORT,
|
|
3302
|
+
rgba16float: gl.HALF_FLOAT,
|
|
3303
|
+
// 128-bit formats
|
|
3304
|
+
rgba32uint: gl.UNSIGNED_INT,
|
|
3305
|
+
rgba32sint: gl.INT,
|
|
3306
|
+
rgba32float: gl.FLOAT,
|
|
3307
|
+
// Depth/stencil formats
|
|
3308
|
+
stencil8: gl.UNSIGNED_BYTE,
|
|
3309
|
+
depth16unorm: gl.UNSIGNED_SHORT,
|
|
3310
|
+
depth24plus: gl.UNSIGNED_INT,
|
|
3311
|
+
"depth24plus-stencil8": gl.UNSIGNED_INT_24_8,
|
|
3312
|
+
depth32float: gl.FLOAT,
|
|
3313
|
+
"depth32float-stencil8": gl.FLOAT_32_UNSIGNED_INT_24_8_REV
|
|
3314
|
+
};
|
|
3315
|
+
}
|
|
3316
|
+
function mapViewDimensionToGlTarget(gl) {
|
|
3317
|
+
return {
|
|
3318
|
+
"2d": gl.TEXTURE_2D,
|
|
3319
|
+
cube: gl.TEXTURE_CUBE_MAP,
|
|
3320
|
+
"1d": null,
|
|
3321
|
+
// WebGL2 only
|
|
3322
|
+
"3d": gl?.TEXTURE_3D || null,
|
|
3323
|
+
"2d-array": gl?.TEXTURE_2D_ARRAY || null,
|
|
3324
|
+
"cube-array": gl?.TEXTURE_CUBE_MAP_ARRAY || null
|
|
3325
|
+
};
|
|
3326
|
+
}
|
|
3327
|
+
const BYTES_PER_PIXEL = 4;
|
|
3328
|
+
class GlTextureSystem {
|
|
3329
|
+
constructor(renderer) {
|
|
3330
|
+
this._glSamplers = /* @__PURE__ */ Object.create(null);
|
|
3331
|
+
this._boundTextures = [];
|
|
3332
|
+
this._activeTextureLocation = -1;
|
|
3333
|
+
this._boundSamplers = /* @__PURE__ */ Object.create(null);
|
|
3334
|
+
this._premultiplyAlpha = false;
|
|
3335
|
+
this._useSeparateSamplers = false;
|
|
3336
|
+
this._renderer = renderer;
|
|
3337
|
+
this._managedTextures = new GCManagedHash({
|
|
3338
|
+
renderer,
|
|
3339
|
+
type: "resource",
|
|
3340
|
+
onUnload: this.onSourceUnload.bind(this),
|
|
3341
|
+
name: "glTexture"
|
|
3342
|
+
});
|
|
3343
|
+
const baseUploaders = {
|
|
3344
|
+
image: glUploadImageResource,
|
|
3345
|
+
buffer: glUploadBufferImageResource,
|
|
3346
|
+
video: glUploadVideoResource,
|
|
3347
|
+
compressed: glUploadCompressedTextureResource
|
|
3348
|
+
};
|
|
3349
|
+
this._uploads = {
|
|
3350
|
+
...baseUploaders,
|
|
3351
|
+
cube: createGlUploadCubeTextureResource(baseUploaders)
|
|
3352
|
+
};
|
|
3353
|
+
}
|
|
3354
|
+
/**
|
|
3355
|
+
* @deprecated since 8.15.0
|
|
3356
|
+
*/
|
|
3357
|
+
get managedTextures() {
|
|
3358
|
+
return Object.values(this._managedTextures.items);
|
|
3359
|
+
}
|
|
3360
|
+
contextChange(gl) {
|
|
3361
|
+
this._gl = gl;
|
|
3362
|
+
if (!this._mapFormatToInternalFormat) {
|
|
3363
|
+
this._mapFormatToInternalFormat = mapFormatToGlInternalFormat(gl, this._renderer.context.extensions);
|
|
3364
|
+
this._mapFormatToType = mapFormatToGlType(gl);
|
|
3365
|
+
this._mapFormatToFormat = mapFormatToGlFormat(gl);
|
|
3366
|
+
this._mapViewDimensionToGlTarget = mapViewDimensionToGlTarget(gl);
|
|
3367
|
+
}
|
|
3368
|
+
this._managedTextures.removeAll(true);
|
|
3369
|
+
this._glSamplers = /* @__PURE__ */ Object.create(null);
|
|
3370
|
+
this._boundSamplers = /* @__PURE__ */ Object.create(null);
|
|
3371
|
+
this._premultiplyAlpha = false;
|
|
3372
|
+
for (let i = 0; i < 16; i++) {
|
|
3373
|
+
this.bind(Texture.EMPTY, i);
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
/**
|
|
3377
|
+
* Initializes a texture source, if it has already been initialized nothing will happen.
|
|
3378
|
+
* @param source - The texture source to initialize.
|
|
3379
|
+
* @returns The initialized texture source.
|
|
3380
|
+
*/
|
|
3381
|
+
initSource(source) {
|
|
3382
|
+
this.bind(source);
|
|
3383
|
+
}
|
|
3384
|
+
bind(texture, location = 0) {
|
|
3385
|
+
const source = texture.source;
|
|
3386
|
+
if (texture) {
|
|
3387
|
+
this.bindSource(source, location);
|
|
3388
|
+
if (this._useSeparateSamplers) {
|
|
3389
|
+
this._bindSampler(source.style, location);
|
|
3390
|
+
}
|
|
3391
|
+
} else {
|
|
3392
|
+
this.bindSource(null, location);
|
|
3393
|
+
if (this._useSeparateSamplers) {
|
|
3394
|
+
this._bindSampler(null, location);
|
|
3395
|
+
}
|
|
3396
|
+
}
|
|
3397
|
+
}
|
|
3398
|
+
bindSource(source, location = 0) {
|
|
3399
|
+
const gl = this._gl;
|
|
3400
|
+
source._gcLastUsed = this._renderer.gc.now;
|
|
3401
|
+
if (this._boundTextures[location] !== source) {
|
|
3402
|
+
this._boundTextures[location] = source;
|
|
3403
|
+
this._activateLocation(location);
|
|
3404
|
+
source || (source = Texture.EMPTY.source);
|
|
3405
|
+
const glTexture = this.getGlSource(source);
|
|
3406
|
+
gl.bindTexture(glTexture.target, glTexture.texture);
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
_bindSampler(style, location = 0) {
|
|
3410
|
+
const gl = this._gl;
|
|
3411
|
+
if (!style) {
|
|
3412
|
+
this._boundSamplers[location] = null;
|
|
3413
|
+
gl.bindSampler(location, null);
|
|
3414
|
+
return;
|
|
3415
|
+
}
|
|
3416
|
+
const sampler = this._getGlSampler(style);
|
|
3417
|
+
if (this._boundSamplers[location] !== sampler) {
|
|
3418
|
+
this._boundSamplers[location] = sampler;
|
|
3419
|
+
gl.bindSampler(location, sampler);
|
|
3420
|
+
}
|
|
3421
|
+
}
|
|
3422
|
+
unbind(texture) {
|
|
3423
|
+
const source = texture.source;
|
|
3424
|
+
const boundTextures = this._boundTextures;
|
|
3425
|
+
const gl = this._gl;
|
|
3426
|
+
for (let i = 0; i < boundTextures.length; i++) {
|
|
3427
|
+
if (boundTextures[i] === source) {
|
|
3428
|
+
this._activateLocation(i);
|
|
3429
|
+
const glTexture = this.getGlSource(source);
|
|
3430
|
+
gl.bindTexture(glTexture.target, null);
|
|
3431
|
+
boundTextures[i] = null;
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3434
|
+
}
|
|
3435
|
+
_activateLocation(location) {
|
|
3436
|
+
if (this._activeTextureLocation !== location) {
|
|
3437
|
+
this._activeTextureLocation = location;
|
|
3438
|
+
this._gl.activeTexture(this._gl.TEXTURE0 + location);
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3441
|
+
_initSource(source) {
|
|
3442
|
+
const gl = this._gl;
|
|
3443
|
+
const glTexture = new GlTexture(gl.createTexture());
|
|
3444
|
+
glTexture.type = this._mapFormatToType[source.format];
|
|
3445
|
+
glTexture.internalFormat = this._mapFormatToInternalFormat[source.format];
|
|
3446
|
+
glTexture.format = this._mapFormatToFormat[source.format];
|
|
3447
|
+
glTexture.target = this._mapViewDimensionToGlTarget[source.viewDimension];
|
|
3448
|
+
if (glTexture.target === null) {
|
|
3449
|
+
throw new Error(`Unsupported view dimension: ${source.viewDimension} with this webgl version: ${this._renderer.context.webGLVersion}`);
|
|
3450
|
+
}
|
|
3451
|
+
if (source.uploadMethodId === "cube") {
|
|
3452
|
+
glTexture.target = gl.TEXTURE_CUBE_MAP;
|
|
3453
|
+
}
|
|
3454
|
+
if (source.autoGenerateMipmaps && (this._renderer.context.supports.nonPowOf2mipmaps || source.isPowerOfTwo)) {
|
|
3455
|
+
const biggestDimension = Math.max(source.width, source.height);
|
|
3456
|
+
source.mipLevelCount = Math.floor(Math.log2(biggestDimension)) + 1;
|
|
3457
|
+
}
|
|
3458
|
+
source._gpuData[this._renderer.uid] = glTexture;
|
|
3459
|
+
const added = this._managedTextures.add(source);
|
|
3460
|
+
if (added) {
|
|
3461
|
+
source.on("update", this.onSourceUpdate, this);
|
|
3462
|
+
source.on("resize", this.onSourceUpdate, this);
|
|
3463
|
+
source.on("styleChange", this.onStyleChange, this);
|
|
3464
|
+
source.on("updateMipmaps", this.onUpdateMipmaps, this);
|
|
3465
|
+
}
|
|
3466
|
+
this.onSourceUpdate(source);
|
|
3467
|
+
this.updateStyle(source, false);
|
|
3468
|
+
return glTexture;
|
|
3469
|
+
}
|
|
3470
|
+
onStyleChange(source) {
|
|
3471
|
+
this.updateStyle(source, false);
|
|
3472
|
+
}
|
|
3473
|
+
updateStyle(source, firstCreation) {
|
|
3474
|
+
const gl = this._gl;
|
|
3475
|
+
const glTexture = this.getGlSource(source);
|
|
3476
|
+
gl.bindTexture(glTexture.target, glTexture.texture);
|
|
3477
|
+
this._boundTextures[this._activeTextureLocation] = source;
|
|
3478
|
+
applyStyleParams(
|
|
3479
|
+
source.style,
|
|
3480
|
+
gl,
|
|
3481
|
+
source.mipLevelCount > 1,
|
|
3482
|
+
this._renderer.context.extensions.anisotropicFiltering,
|
|
3483
|
+
"texParameteri",
|
|
3484
|
+
glTexture.target,
|
|
3485
|
+
// will force a clamp to edge if the texture is not a power of two
|
|
3486
|
+
!this._renderer.context.supports.nonPowOf2wrapping && !source.isPowerOfTwo,
|
|
3487
|
+
firstCreation
|
|
3488
|
+
);
|
|
3489
|
+
}
|
|
3490
|
+
onSourceUnload(source, contextLost = false) {
|
|
3491
|
+
const glTexture = source._gpuData[this._renderer.uid];
|
|
3492
|
+
if (!glTexture) return;
|
|
3493
|
+
if (!contextLost) {
|
|
3494
|
+
this.unbind(source);
|
|
3495
|
+
this._gl.deleteTexture(glTexture.texture);
|
|
3496
|
+
}
|
|
3497
|
+
source.off("update", this.onSourceUpdate, this);
|
|
3498
|
+
source.off("resize", this.onSourceUpdate, this);
|
|
3499
|
+
source.off("styleChange", this.onStyleChange, this);
|
|
3500
|
+
source.off("updateMipmaps", this.onUpdateMipmaps, this);
|
|
3501
|
+
}
|
|
3502
|
+
onSourceUpdate(source) {
|
|
3503
|
+
const gl = this._gl;
|
|
3504
|
+
const glTexture = this.getGlSource(source);
|
|
3505
|
+
gl.bindTexture(glTexture.target, glTexture.texture);
|
|
3506
|
+
this._boundTextures[this._activeTextureLocation] = source;
|
|
3507
|
+
const premultipliedAlpha = source.alphaMode === "premultiply-alpha-on-upload";
|
|
3508
|
+
if (this._premultiplyAlpha !== premultipliedAlpha) {
|
|
3509
|
+
this._premultiplyAlpha = premultipliedAlpha;
|
|
3510
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultipliedAlpha);
|
|
3511
|
+
}
|
|
3512
|
+
if (this._uploads[source.uploadMethodId]) {
|
|
3513
|
+
this._uploads[source.uploadMethodId].upload(source, glTexture, gl, this._renderer.context.webGLVersion);
|
|
3514
|
+
} else if (glTexture.target === gl.TEXTURE_2D) {
|
|
3515
|
+
this._initEmptyTexture2D(glTexture, source);
|
|
3516
|
+
} else if (glTexture.target === gl.TEXTURE_2D_ARRAY) {
|
|
3517
|
+
this._initEmptyTexture2DArray(glTexture, source);
|
|
3518
|
+
} else if (glTexture.target === gl.TEXTURE_CUBE_MAP) {
|
|
3519
|
+
this._initEmptyTextureCube(glTexture, source);
|
|
3520
|
+
} else {
|
|
3521
|
+
throw new Error("[GlTextureSystem] Unsupported texture target for empty allocation.");
|
|
3522
|
+
}
|
|
3523
|
+
this._applyMipRange(glTexture, source);
|
|
3524
|
+
if (source.autoGenerateMipmaps && source.mipLevelCount > 1) {
|
|
3525
|
+
this.onUpdateMipmaps(source, false);
|
|
3526
|
+
}
|
|
3527
|
+
}
|
|
3528
|
+
onUpdateMipmaps(source, bind = true) {
|
|
3529
|
+
if (bind) this.bindSource(source, 0);
|
|
3530
|
+
const glTexture = this.getGlSource(source);
|
|
3531
|
+
this._gl.generateMipmap(glTexture.target);
|
|
3532
|
+
}
|
|
3533
|
+
_initEmptyTexture2D(glTexture, source) {
|
|
3534
|
+
const gl = this._gl;
|
|
3535
|
+
gl.texImage2D(
|
|
3536
|
+
gl.TEXTURE_2D,
|
|
3537
|
+
0,
|
|
3538
|
+
glTexture.internalFormat,
|
|
3539
|
+
source.pixelWidth,
|
|
3540
|
+
source.pixelHeight,
|
|
3541
|
+
0,
|
|
3542
|
+
glTexture.format,
|
|
3543
|
+
glTexture.type,
|
|
3544
|
+
null
|
|
3545
|
+
);
|
|
3546
|
+
let w = Math.max(source.pixelWidth >> 1, 1);
|
|
3547
|
+
let h = Math.max(source.pixelHeight >> 1, 1);
|
|
3548
|
+
for (let level = 1; level < source.mipLevelCount; level++) {
|
|
3549
|
+
gl.texImage2D(
|
|
3550
|
+
gl.TEXTURE_2D,
|
|
3551
|
+
level,
|
|
3552
|
+
glTexture.internalFormat,
|
|
3553
|
+
w,
|
|
3554
|
+
h,
|
|
3555
|
+
0,
|
|
3556
|
+
glTexture.format,
|
|
3557
|
+
glTexture.type,
|
|
3558
|
+
null
|
|
3559
|
+
);
|
|
3560
|
+
w = Math.max(w >> 1, 1);
|
|
3561
|
+
h = Math.max(h >> 1, 1);
|
|
3562
|
+
}
|
|
3563
|
+
}
|
|
3564
|
+
_initEmptyTexture2DArray(glTexture, source) {
|
|
3565
|
+
if (this._renderer.context.webGLVersion !== 2) {
|
|
3566
|
+
throw new Error("[GlTextureSystem] TEXTURE_2D_ARRAY requires WebGL2.");
|
|
3567
|
+
}
|
|
3568
|
+
const gl2 = this._gl;
|
|
3569
|
+
const depth = Math.max(source.arrayLayerCount | 0, 1);
|
|
3570
|
+
gl2.texImage3D(
|
|
3571
|
+
gl2.TEXTURE_2D_ARRAY,
|
|
3572
|
+
0,
|
|
3573
|
+
glTexture.internalFormat,
|
|
3574
|
+
source.pixelWidth,
|
|
3575
|
+
source.pixelHeight,
|
|
3576
|
+
depth,
|
|
3577
|
+
0,
|
|
3578
|
+
glTexture.format,
|
|
3579
|
+
glTexture.type,
|
|
3580
|
+
null
|
|
3581
|
+
);
|
|
3582
|
+
let w = Math.max(source.pixelWidth >> 1, 1);
|
|
3583
|
+
let h = Math.max(source.pixelHeight >> 1, 1);
|
|
3584
|
+
for (let level = 1; level < source.mipLevelCount; level++) {
|
|
3585
|
+
gl2.texImage3D(
|
|
3586
|
+
gl2.TEXTURE_2D_ARRAY,
|
|
3587
|
+
level,
|
|
3588
|
+
glTexture.internalFormat,
|
|
3589
|
+
w,
|
|
3590
|
+
h,
|
|
3591
|
+
depth,
|
|
3592
|
+
0,
|
|
3593
|
+
glTexture.format,
|
|
3594
|
+
glTexture.type,
|
|
3595
|
+
null
|
|
3596
|
+
);
|
|
3597
|
+
w = Math.max(w >> 1, 1);
|
|
3598
|
+
h = Math.max(h >> 1, 1);
|
|
3599
|
+
}
|
|
3600
|
+
}
|
|
3601
|
+
_initEmptyTextureCube(glTexture, source) {
|
|
3602
|
+
const gl = this._gl;
|
|
3603
|
+
const totalCubeFaces = 6;
|
|
3604
|
+
for (let face = 0; face < totalCubeFaces; face++) {
|
|
3605
|
+
gl.texImage2D(
|
|
3606
|
+
gl.TEXTURE_CUBE_MAP_POSITIVE_X + face,
|
|
3607
|
+
0,
|
|
3608
|
+
glTexture.internalFormat,
|
|
3609
|
+
source.pixelWidth,
|
|
3610
|
+
source.pixelHeight,
|
|
3611
|
+
0,
|
|
3612
|
+
glTexture.format,
|
|
3613
|
+
glTexture.type,
|
|
3614
|
+
null
|
|
3615
|
+
);
|
|
3616
|
+
}
|
|
3617
|
+
let w = Math.max(source.pixelWidth >> 1, 1);
|
|
3618
|
+
let h = Math.max(source.pixelHeight >> 1, 1);
|
|
3619
|
+
for (let level = 1; level < source.mipLevelCount; level++) {
|
|
3620
|
+
for (let face = 0; face < totalCubeFaces; face++) {
|
|
3621
|
+
gl.texImage2D(
|
|
3622
|
+
gl.TEXTURE_CUBE_MAP_POSITIVE_X + face,
|
|
3623
|
+
level,
|
|
3624
|
+
glTexture.internalFormat,
|
|
3625
|
+
w,
|
|
3626
|
+
h,
|
|
3627
|
+
0,
|
|
3628
|
+
glTexture.format,
|
|
3629
|
+
glTexture.type,
|
|
3630
|
+
null
|
|
3631
|
+
);
|
|
3632
|
+
}
|
|
3633
|
+
w = Math.max(w >> 1, 1);
|
|
3634
|
+
h = Math.max(h >> 1, 1);
|
|
3635
|
+
}
|
|
3636
|
+
}
|
|
3637
|
+
/**
|
|
3638
|
+
* Applies a mip range to the currently-bound texture so WebGL2 considers the texture "mipmap complete"
|
|
3639
|
+
* for the declared `mipLevelCount` (especially important for partial mip chains rendered via FBO).
|
|
3640
|
+
* @param glTexture - The GL texture wrapper.
|
|
3641
|
+
* @param source - The texture source describing mipLevelCount.
|
|
3642
|
+
*/
|
|
3643
|
+
_applyMipRange(glTexture, source) {
|
|
3644
|
+
if (this._renderer.context.webGLVersion !== 2) return;
|
|
3645
|
+
const gl = this._gl;
|
|
3646
|
+
const maxLevel = Math.max((source.mipLevelCount | 0) - 1, 0);
|
|
3647
|
+
gl.texParameteri(glTexture.target, gl.TEXTURE_BASE_LEVEL, 0);
|
|
3648
|
+
gl.texParameteri(glTexture.target, gl.TEXTURE_MAX_LEVEL, maxLevel);
|
|
3649
|
+
}
|
|
3650
|
+
_initSampler(style) {
|
|
3651
|
+
const gl = this._gl;
|
|
3652
|
+
const glSampler = this._gl.createSampler();
|
|
3653
|
+
this._glSamplers[style._resourceId] = glSampler;
|
|
3654
|
+
applyStyleParams(
|
|
3655
|
+
style,
|
|
3656
|
+
gl,
|
|
3657
|
+
this._boundTextures[this._activeTextureLocation].mipLevelCount > 1,
|
|
3658
|
+
this._renderer.context.extensions.anisotropicFiltering,
|
|
3659
|
+
"samplerParameteri",
|
|
3660
|
+
glSampler,
|
|
3661
|
+
false,
|
|
3662
|
+
true
|
|
3663
|
+
);
|
|
3664
|
+
return this._glSamplers[style._resourceId];
|
|
3665
|
+
}
|
|
3666
|
+
_getGlSampler(sampler) {
|
|
3667
|
+
return this._glSamplers[sampler._resourceId] || this._initSampler(sampler);
|
|
3668
|
+
}
|
|
3669
|
+
getGlSource(source) {
|
|
3670
|
+
source._gcLastUsed = this._renderer.gc.now;
|
|
3671
|
+
return source._gpuData[this._renderer.uid] || this._initSource(source);
|
|
3672
|
+
}
|
|
3673
|
+
generateCanvas(texture) {
|
|
3674
|
+
const { pixels, width, height } = this.getPixels(texture);
|
|
3675
|
+
const canvas = DOMAdapter.get().createCanvas();
|
|
3676
|
+
canvas.width = width;
|
|
3677
|
+
canvas.height = height;
|
|
3678
|
+
const ctx = canvas.getContext("2d");
|
|
3679
|
+
if (ctx) {
|
|
3680
|
+
const imageData = ctx.createImageData(width, height);
|
|
3681
|
+
imageData.data.set(pixels);
|
|
3682
|
+
ctx.putImageData(imageData, 0, 0);
|
|
3683
|
+
}
|
|
3684
|
+
return canvas;
|
|
3685
|
+
}
|
|
3686
|
+
getPixels(texture) {
|
|
3687
|
+
const resolution = texture.source.resolution;
|
|
3688
|
+
const frame = texture.frame;
|
|
3689
|
+
const width = Math.max(Math.round(frame.width * resolution), 1);
|
|
3690
|
+
const height = Math.max(Math.round(frame.height * resolution), 1);
|
|
3691
|
+
const pixels = new Uint8Array(BYTES_PER_PIXEL * width * height);
|
|
3692
|
+
const renderer = this._renderer;
|
|
3693
|
+
const renderTarget = renderer.renderTarget.getRenderTarget(texture);
|
|
3694
|
+
const glRenterTarget = renderer.renderTarget.getGpuRenderTarget(renderTarget);
|
|
3695
|
+
const gl = renderer.gl;
|
|
3696
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, glRenterTarget.resolveTargetFramebuffer);
|
|
3697
|
+
gl.readPixels(
|
|
3698
|
+
Math.round(frame.x * resolution),
|
|
3699
|
+
Math.round(frame.y * resolution),
|
|
3700
|
+
width,
|
|
3701
|
+
height,
|
|
3702
|
+
gl.RGBA,
|
|
3703
|
+
gl.UNSIGNED_BYTE,
|
|
3704
|
+
pixels
|
|
3705
|
+
);
|
|
3706
|
+
return { pixels: new Uint8ClampedArray(pixels.buffer), width, height };
|
|
3707
|
+
}
|
|
3708
|
+
destroy() {
|
|
3709
|
+
this._managedTextures.destroy();
|
|
3710
|
+
this._glSamplers = null;
|
|
3711
|
+
this._boundTextures = null;
|
|
3712
|
+
this._boundSamplers = null;
|
|
3713
|
+
this._mapFormatToInternalFormat = null;
|
|
3714
|
+
this._mapFormatToType = null;
|
|
3715
|
+
this._mapFormatToFormat = null;
|
|
3716
|
+
this._uploads = null;
|
|
3717
|
+
this._renderer = null;
|
|
3718
|
+
}
|
|
3719
|
+
resetState() {
|
|
3720
|
+
this._activeTextureLocation = -1;
|
|
3721
|
+
this._boundTextures.fill(Texture.EMPTY.source);
|
|
3722
|
+
this._boundSamplers = /* @__PURE__ */ Object.create(null);
|
|
3723
|
+
const gl = this._gl;
|
|
3724
|
+
this._premultiplyAlpha = false;
|
|
3725
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._premultiplyAlpha);
|
|
3726
|
+
}
|
|
3727
|
+
}
|
|
3728
|
+
GlTextureSystem.extension = {
|
|
3729
|
+
type: [
|
|
3730
|
+
ExtensionType.WebGLSystem
|
|
3731
|
+
],
|
|
3732
|
+
name: "texture"
|
|
3733
|
+
};
|
|
3734
|
+
class GlGraphicsAdaptor {
|
|
3735
|
+
contextChange(renderer) {
|
|
3736
|
+
const uniforms = new UniformGroup({
|
|
3737
|
+
uColor: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" },
|
|
3738
|
+
uTransformMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
|
|
3739
|
+
uRound: { value: 0, type: "f32" }
|
|
3740
|
+
});
|
|
3741
|
+
const maxTextures = renderer.limits.maxBatchableTextures;
|
|
3742
|
+
const glProgram = compileHighShaderGlProgram({
|
|
3743
|
+
name: "graphics",
|
|
3744
|
+
bits: [
|
|
3745
|
+
colorBitGl,
|
|
3746
|
+
generateTextureBatchBitGl(maxTextures),
|
|
3747
|
+
localUniformBitGl,
|
|
3748
|
+
roundPixelsBitGl
|
|
3749
|
+
]
|
|
3750
|
+
});
|
|
3751
|
+
this.shader = new Shader({
|
|
3752
|
+
glProgram,
|
|
3753
|
+
resources: {
|
|
3754
|
+
localUniforms: uniforms,
|
|
3755
|
+
batchSamplers: getBatchSamplersUniformGroup(maxTextures)
|
|
3756
|
+
}
|
|
3757
|
+
});
|
|
3758
|
+
}
|
|
3759
|
+
execute(graphicsPipe, renderable) {
|
|
3760
|
+
const context = renderable.context;
|
|
3761
|
+
const shader = context.customShader || this.shader;
|
|
3762
|
+
const renderer = graphicsPipe.renderer;
|
|
3763
|
+
const contextSystem = renderer.graphicsContext;
|
|
3764
|
+
const {
|
|
3765
|
+
batcher,
|
|
3766
|
+
instructions
|
|
3767
|
+
} = contextSystem.getContextRenderData(context);
|
|
3768
|
+
shader.groups[0] = renderer.globalUniforms.bindGroup;
|
|
3769
|
+
renderer.state.set(graphicsPipe.state);
|
|
3770
|
+
renderer.shader.bind(shader);
|
|
3771
|
+
renderer.geometry.bind(batcher.geometry, shader.glProgram);
|
|
3772
|
+
const batches = instructions.instructions;
|
|
3773
|
+
for (let i = 0; i < instructions.instructionSize; i++) {
|
|
3774
|
+
const batch = batches[i];
|
|
3775
|
+
if (batch.size) {
|
|
3776
|
+
for (let j = 0; j < batch.textures.count; j++) {
|
|
3777
|
+
renderer.texture.bind(batch.textures.textures[j], j);
|
|
3778
|
+
}
|
|
3779
|
+
renderer.geometry.draw(batch.topology, batch.size, batch.start);
|
|
3780
|
+
}
|
|
3781
|
+
}
|
|
3782
|
+
}
|
|
3783
|
+
destroy() {
|
|
3784
|
+
this.shader.destroy(true);
|
|
3785
|
+
this.shader = null;
|
|
3786
|
+
}
|
|
3787
|
+
}
|
|
3788
|
+
GlGraphicsAdaptor.extension = {
|
|
3789
|
+
type: [
|
|
3790
|
+
ExtensionType.WebGLPipesAdaptor
|
|
3791
|
+
],
|
|
3792
|
+
name: "graphics"
|
|
3793
|
+
};
|
|
3794
|
+
class GlMeshAdaptor {
|
|
3795
|
+
init() {
|
|
3796
|
+
const glProgram = compileHighShaderGlProgram({
|
|
3797
|
+
name: "mesh",
|
|
3798
|
+
bits: [
|
|
3799
|
+
localUniformBitGl,
|
|
3800
|
+
textureBitGl,
|
|
3801
|
+
roundPixelsBitGl
|
|
3802
|
+
]
|
|
3803
|
+
});
|
|
3804
|
+
this._shader = new Shader({
|
|
3805
|
+
glProgram,
|
|
3806
|
+
resources: {
|
|
3807
|
+
uTexture: Texture.EMPTY.source,
|
|
3808
|
+
textureUniforms: {
|
|
3809
|
+
uTextureMatrix: { type: "mat3x3<f32>", value: new Matrix() }
|
|
3810
|
+
}
|
|
3811
|
+
}
|
|
3812
|
+
});
|
|
3813
|
+
}
|
|
3814
|
+
execute(meshPipe, mesh) {
|
|
3815
|
+
const renderer = meshPipe.renderer;
|
|
3816
|
+
let shader = mesh._shader;
|
|
3817
|
+
if (!shader) {
|
|
3818
|
+
shader = this._shader;
|
|
3819
|
+
const texture = mesh.texture;
|
|
3820
|
+
const source = texture.source;
|
|
3821
|
+
shader.resources.uTexture = source;
|
|
3822
|
+
shader.resources.uSampler = source.style;
|
|
3823
|
+
shader.resources.textureUniforms.uniforms.uTextureMatrix = texture.textureMatrix.mapCoord;
|
|
3824
|
+
} else if (!shader.glProgram) {
|
|
3825
|
+
warn("Mesh shader has no glProgram", mesh.shader);
|
|
3826
|
+
return;
|
|
3827
|
+
}
|
|
3828
|
+
shader.groups[100] = renderer.globalUniforms.bindGroup;
|
|
3829
|
+
shader.groups[101] = meshPipe.localUniformsBindGroup;
|
|
3830
|
+
renderer.encoder.draw({
|
|
3831
|
+
geometry: mesh._geometry,
|
|
3832
|
+
shader,
|
|
3833
|
+
state: mesh.state
|
|
3834
|
+
});
|
|
3835
|
+
}
|
|
3836
|
+
destroy() {
|
|
3837
|
+
this._shader.destroy(true);
|
|
3838
|
+
this._shader = null;
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3841
|
+
GlMeshAdaptor.extension = {
|
|
3842
|
+
type: [
|
|
3843
|
+
ExtensionType.WebGLPipesAdaptor
|
|
3844
|
+
],
|
|
3845
|
+
name: "mesh"
|
|
3846
|
+
};
|
|
3847
|
+
const DefaultWebGLSystems = [
|
|
3848
|
+
...SharedSystems,
|
|
3849
|
+
GlUboSystem,
|
|
3850
|
+
GlBackBufferSystem,
|
|
3851
|
+
GlContextSystem,
|
|
3852
|
+
GlLimitsSystem,
|
|
3853
|
+
GlBufferSystem,
|
|
3854
|
+
GlTextureSystem,
|
|
3855
|
+
GlRenderTargetSystem,
|
|
3856
|
+
GlGeometrySystem,
|
|
3857
|
+
GlUniformGroupSystem,
|
|
3858
|
+
GlShaderSystem,
|
|
3859
|
+
GlEncoderSystem,
|
|
3860
|
+
GlStateSystem,
|
|
3861
|
+
GlStencilSystem,
|
|
3862
|
+
GlColorMaskSystem
|
|
3863
|
+
];
|
|
3864
|
+
const DefaultWebGLPipes = [...SharedRenderPipes];
|
|
3865
|
+
const DefaultWebGLAdapters = [GlBatchAdaptor, GlMeshAdaptor, GlGraphicsAdaptor];
|
|
3866
|
+
const systems = [];
|
|
3867
|
+
const renderPipes = [];
|
|
3868
|
+
const renderPipeAdaptors = [];
|
|
3869
|
+
extensions.handleByNamedList(ExtensionType.WebGLSystem, systems);
|
|
3870
|
+
extensions.handleByNamedList(ExtensionType.WebGLPipes, renderPipes);
|
|
3871
|
+
extensions.handleByNamedList(ExtensionType.WebGLPipesAdaptor, renderPipeAdaptors);
|
|
3872
|
+
extensions.add(...DefaultWebGLSystems, ...DefaultWebGLPipes, ...DefaultWebGLAdapters);
|
|
3873
|
+
class WebGLRenderer extends AbstractRenderer {
|
|
3874
|
+
constructor() {
|
|
3875
|
+
const systemConfig = {
|
|
3876
|
+
name: "webgl",
|
|
3877
|
+
type: RendererType.WEBGL,
|
|
3878
|
+
systems,
|
|
3879
|
+
renderPipes,
|
|
3880
|
+
renderPipeAdaptors
|
|
3881
|
+
};
|
|
3882
|
+
super(systemConfig);
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
3885
|
+
export {
|
|
3886
|
+
WebGLRenderer
|
|
3887
|
+
};
|