@spiffcommerce/preview 3.6.2-rc.8 → 4.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.
Files changed (45) hide show
  1. package/dist/index.esm.js +1576 -38
  2. package/dist/index.umd.js +1 -0
  3. package/package.json +4 -6
  4. package/dist/_tslib.esm.js +0 -33
  5. package/dist/animation.esm.js +0 -1364
  6. package/dist/assetCache.esm.js +0 -6
  7. package/dist/assetCache.esm2.js +0 -825
  8. package/dist/blurPostProcess.esm.js +0 -327
  9. package/dist/bumpVertex.esm.js +0 -497
  10. package/dist/compatibilityOptions.esm.js +0 -68
  11. package/dist/configuration.esm.js +0 -121
  12. package/dist/core.esm.js +0 -8135
  13. package/dist/dynamicTexture.esm.js +0 -105
  14. package/dist/dynamicTexture.esm2.js +0 -238
  15. package/dist/easing.esm.js +0 -130
  16. package/dist/effectFallbacks.esm.js +0 -378
  17. package/dist/engine.esm.js +0 -25504
  18. package/dist/glbLoaderExtensions.esm.js +0 -690
  19. package/dist/glowLayer.esm.js +0 -1621
  20. package/dist/glowLayerManager.esm.js +0 -50
  21. package/dist/guid.esm.js +0 -21
  22. package/dist/hdrFilteringFunctions.esm.js +0 -816
  23. package/dist/helperFunctions.esm.js +0 -5145
  24. package/dist/material.esm.js +0 -115
  25. package/dist/material.esm2.js +0 -5245
  26. package/dist/math.axis.esm.js +0 -35
  27. package/dist/math.color.esm.js +0 -1661
  28. package/dist/math.path.esm.js +0 -15
  29. package/dist/math.size.esm.js +0 -137
  30. package/dist/mesh.esm.js +0 -11170
  31. package/dist/modelContainer.esm.js +0 -1895
  32. package/dist/node.esm.js +0 -795
  33. package/dist/pbrBRDFFunctions.esm.js +0 -124
  34. package/dist/pbrMaterial.esm.js +8 -8739
  35. package/dist/productAnimations.esm.js +0 -182
  36. package/dist/productCamera.esm.js +0 -14
  37. package/dist/productCamera.esm2.js +0 -3870
  38. package/dist/renderConstants.esm.js +0 -116
  39. package/dist/renderingPipeline.esm.js +0 -18
  40. package/dist/renderingPipeline.esm2.js +1 -3594
  41. package/dist/sceneLoaderFlags.esm.js +0 -51
  42. package/dist/types.esm.js +0 -30
  43. package/dist/variants.esm.js +0 -16
  44. package/dist/variants.esm2.js +0 -3097
  45. package/dist/webRequest.esm.js +0 -7777
@@ -1,3097 +0,0 @@
1
- import { _ as __awaiter } from './_tslib.esm.js';
2
- import { S as SceneLoader, g as getAssetContainer } from './assetCache.esm2.js';
3
- import { T as ThinEngine, I as InternalTexture, a as InternalTextureSource, L as Logger, q as RandomGUID, r as LoadImage, c as Tools, e as ShaderStore } from './engine.esm.js';
4
- import { _ as __decorate, M as Matrix, O as Observable, V as Vector3, T as TmpVectors, S as SerializationHelper, s as serialize, d as serializeAsVector3, k as serializeAsMatrix, E as EngineStore } from './webRequest.esm.js';
5
- import { T as Texture, B as BaseTexture, E as EffectWrapper, a as EffectRenderer } from './helperFunctions.esm.js';
6
- import { G as GetClass, R as RegisterClass, S as Scalar, b as ToGammaSpace } from './math.color.esm.js';
7
- import { C as CubeMapToSphericalPolynomialTools, T as ToHalfFloat } from './hdrFilteringFunctions.esm.js';
8
- import './math.axis.esm.js';
9
- import './math.path.esm.js';
10
- import './pbrBRDFFunctions.esm.js';
11
- import { calculateMaterialProperties, applyDownloadedTexture } from './material.esm.js';
12
-
13
- ThinEngine.prototype._createDepthStencilCubeTexture = function (size, options, rtWrapper) {
14
- const internalTexture = new InternalTexture(this, InternalTextureSource.DepthStencil);
15
- internalTexture.isCube = true;
16
- if (this.webGLVersion === 1) {
17
- Logger.Error("Depth cube texture is not supported by WebGL 1.");
18
- return internalTexture;
19
- }
20
- const internalOptions = Object.assign({ bilinearFiltering: false, comparisonFunction: 0, generateStencil: false }, options);
21
- const gl = this._gl;
22
- this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, internalTexture, true);
23
- this._setupDepthStencilTexture(internalTexture, size, internalOptions.generateStencil, internalOptions.bilinearFiltering, internalOptions.comparisonFunction);
24
- rtWrapper._depthStencilTexture = internalTexture;
25
- rtWrapper._depthStencilTextureWithStencil = internalOptions.generateStencil;
26
- // Create the depth/stencil buffer
27
- for (let face = 0; face < 6; face++) {
28
- if (internalOptions.generateStencil) {
29
- gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, gl.DEPTH24_STENCIL8, size, size, 0, gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8, null);
30
- }
31
- else {
32
- gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, gl.DEPTH_COMPONENT24, size, size, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null);
33
- }
34
- }
35
- this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
36
- this._internalTexturesCache.push(internalTexture);
37
- return internalTexture;
38
- };
39
- ThinEngine.prototype._partialLoadFile = function (url, index, loadedFiles, onfinish, onErrorCallBack = null) {
40
- const onload = (data) => {
41
- loadedFiles[index] = data;
42
- loadedFiles._internalCount++;
43
- if (loadedFiles._internalCount === 6) {
44
- onfinish(loadedFiles);
45
- }
46
- };
47
- const onerror = (request, exception) => {
48
- if (onErrorCallBack && request) {
49
- onErrorCallBack(request.status + " " + request.statusText, exception);
50
- }
51
- };
52
- this._loadFile(url, onload, undefined, undefined, true, onerror);
53
- };
54
- ThinEngine.prototype._cascadeLoadFiles = function (scene, onfinish, files, onError = null) {
55
- const loadedFiles = [];
56
- loadedFiles._internalCount = 0;
57
- for (let index = 0; index < 6; index++) {
58
- this._partialLoadFile(files[index], index, loadedFiles, onfinish, onError);
59
- }
60
- };
61
- ThinEngine.prototype._cascadeLoadImgs = function (scene, texture, onfinish, files, onError = null, mimeType) {
62
- const loadedImages = [];
63
- loadedImages._internalCount = 0;
64
- for (let index = 0; index < 6; index++) {
65
- this._partialLoadImg(files[index], index, loadedImages, scene, texture, onfinish, onError, mimeType);
66
- }
67
- };
68
- ThinEngine.prototype._partialLoadImg = function (url, index, loadedImages, scene, texture, onfinish, onErrorCallBack = null, mimeType) {
69
- const tokenPendingData = RandomGUID();
70
- const onload = (img) => {
71
- loadedImages[index] = img;
72
- loadedImages._internalCount++;
73
- if (scene) {
74
- scene.removePendingData(tokenPendingData);
75
- }
76
- if (loadedImages._internalCount === 6 && onfinish) {
77
- onfinish(texture, loadedImages);
78
- }
79
- };
80
- const onerror = (message, exception) => {
81
- if (scene) {
82
- scene.removePendingData(tokenPendingData);
83
- }
84
- if (onErrorCallBack) {
85
- onErrorCallBack(message, exception);
86
- }
87
- };
88
- LoadImage(url, onload, onerror, scene ? scene.offlineProvider : null, mimeType);
89
- if (scene) {
90
- scene.addPendingData(tokenPendingData);
91
- }
92
- };
93
- ThinEngine.prototype._setCubeMapTextureParams = function (texture, loadMipmap, maxLevel) {
94
- const gl = this._gl;
95
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
96
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, loadMipmap ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR);
97
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
98
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
99
- texture.samplingMode = loadMipmap ? 3 : 2;
100
- if (loadMipmap && this.getCaps().textureMaxLevel && maxLevel !== undefined && maxLevel > 0) {
101
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAX_LEVEL, maxLevel);
102
- texture._maxLodLevel = maxLevel;
103
- }
104
- this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
105
- };
106
- ThinEngine.prototype.createCubeTextureBase = function (rootUrl, scene, files, noMipmap, onLoad = null, onError = null, format, forcedExtension = null, createPolynomials = false, lodScale = 0, lodOffset = 0, fallback = null, beforeLoadCubeDataCallback = null, imageHandler = null, useSRGBBuffer = false) {
107
- const texture = fallback ? fallback : new InternalTexture(this, InternalTextureSource.Cube);
108
- texture.isCube = true;
109
- texture.url = rootUrl;
110
- texture.generateMipMaps = !noMipmap;
111
- texture._lodGenerationScale = lodScale;
112
- texture._lodGenerationOffset = lodOffset;
113
- texture._useSRGBBuffer = !!useSRGBBuffer && this._caps.supportSRGBBuffers && (this.webGLVersion > 1 || this.isWebGPU || !!noMipmap);
114
- if (texture !== fallback) {
115
- texture.label = rootUrl.substring(0, 60); // default label, can be overriden by the caller
116
- }
117
- if (!this._doNotHandleContextLost) {
118
- texture._extension = forcedExtension;
119
- texture._files = files;
120
- }
121
- const originalRootUrl = rootUrl;
122
- if (this._transformTextureUrl && !fallback) {
123
- rootUrl = this._transformTextureUrl(rootUrl);
124
- }
125
- const rootUrlWithoutUriParams = rootUrl.split("?")[0];
126
- const lastDot = rootUrlWithoutUriParams.lastIndexOf(".");
127
- const extension = forcedExtension ? forcedExtension : lastDot > -1 ? rootUrlWithoutUriParams.substring(lastDot).toLowerCase() : "";
128
- let loader = null;
129
- for (const availableLoader of ThinEngine._TextureLoaders) {
130
- if (availableLoader.canLoad(extension)) {
131
- loader = availableLoader;
132
- break;
133
- }
134
- }
135
- const onInternalError = (request, exception) => {
136
- if (rootUrl === originalRootUrl) {
137
- if (onError && request) {
138
- onError(request.status + " " + request.statusText, exception);
139
- }
140
- }
141
- else {
142
- // fall back to the original url if the transformed url fails to load
143
- Logger.Warn(`Failed to load ${rootUrl}, falling back to the ${originalRootUrl}`);
144
- this.createCubeTextureBase(originalRootUrl, scene, files, !!noMipmap, onLoad, onError, format, forcedExtension, createPolynomials, lodScale, lodOffset, texture, beforeLoadCubeDataCallback, imageHandler, useSRGBBuffer);
145
- }
146
- };
147
- if (loader) {
148
- const onloaddata = (data) => {
149
- if (beforeLoadCubeDataCallback) {
150
- beforeLoadCubeDataCallback(texture, data);
151
- }
152
- loader.loadCubeData(data, texture, createPolynomials, onLoad, onError);
153
- };
154
- if (files && files.length === 6) {
155
- if (loader.supportCascades) {
156
- this._cascadeLoadFiles(scene, (images) => onloaddata(images.map((image) => new Uint8Array(image))), files, onError);
157
- }
158
- else {
159
- if (onError) {
160
- onError("Textures type does not support cascades.");
161
- }
162
- else {
163
- Logger.Warn("Texture loader does not support cascades.");
164
- }
165
- }
166
- }
167
- else {
168
- this._loadFile(rootUrl, (data) => onloaddata(new Uint8Array(data)), undefined, undefined, true, onInternalError);
169
- }
170
- }
171
- else {
172
- if (!files) {
173
- throw new Error("Cannot load cubemap because files were not defined");
174
- }
175
- this._cascadeLoadImgs(scene, texture, (texture, imgs) => {
176
- if (imageHandler) {
177
- imageHandler(texture, imgs);
178
- }
179
- }, files, onError);
180
- }
181
- this._internalTexturesCache.push(texture);
182
- return texture;
183
- };
184
- ThinEngine.prototype.createCubeTexture = function (rootUrl, scene, files, noMipmap, onLoad = null, onError = null, format, forcedExtension = null, createPolynomials = false, lodScale = 0, lodOffset = 0, fallback = null, loaderOptions, useSRGBBuffer = false) {
185
- const gl = this._gl;
186
- return this.createCubeTextureBase(rootUrl, scene, files, !!noMipmap, onLoad, onError, format, forcedExtension, createPolynomials, lodScale, lodOffset, fallback, (texture) => this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true), (texture, imgs) => {
187
- const width = this.needPOTTextures ? ThinEngine.GetExponentOfTwo(imgs[0].width, this._caps.maxCubemapTextureSize) : imgs[0].width;
188
- const height = width;
189
- const faces = [
190
- gl.TEXTURE_CUBE_MAP_POSITIVE_X,
191
- gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
192
- gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
193
- gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
194
- gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
195
- gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,
196
- ];
197
- this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
198
- this._unpackFlipY(false);
199
- const internalFormat = format ? this._getInternalFormat(format, texture._useSRGBBuffer) : texture._useSRGBBuffer ? this._glSRGBExtensionValues.SRGB8_ALPHA8 : gl.RGBA;
200
- let texelFormat = format ? this._getInternalFormat(format) : gl.RGBA;
201
- if (texture._useSRGBBuffer && this.webGLVersion === 1) {
202
- texelFormat = internalFormat;
203
- }
204
- for (let index = 0; index < faces.length; index++) {
205
- if (imgs[index].width !== width || imgs[index].height !== height) {
206
- this._prepareWorkingCanvas();
207
- if (!this._workingCanvas || !this._workingContext) {
208
- Logger.Warn("Cannot create canvas to resize texture.");
209
- return;
210
- }
211
- this._workingCanvas.width = width;
212
- this._workingCanvas.height = height;
213
- this._workingContext.drawImage(imgs[index], 0, 0, imgs[index].width, imgs[index].height, 0, 0, width, height);
214
- gl.texImage2D(faces[index], 0, internalFormat, texelFormat, gl.UNSIGNED_BYTE, this._workingCanvas);
215
- }
216
- else {
217
- gl.texImage2D(faces[index], 0, internalFormat, texelFormat, gl.UNSIGNED_BYTE, imgs[index]);
218
- }
219
- }
220
- if (!noMipmap) {
221
- gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
222
- }
223
- this._setCubeMapTextureParams(texture, !noMipmap);
224
- texture.width = width;
225
- texture.height = height;
226
- texture.isReady = true;
227
- if (format) {
228
- texture.format = format;
229
- }
230
- texture.onLoadedObservable.notifyObservers(texture);
231
- texture.onLoadedObservable.clear();
232
- if (onLoad) {
233
- onLoad();
234
- }
235
- }, !!useSRGBBuffer);
236
- };
237
-
238
- /**
239
- * Class for creating a cube texture
240
- */
241
- class CubeTexture extends BaseTexture {
242
- /**
243
- * Gets or sets the size of the bounding box associated with the cube texture
244
- * When defined, the cubemap will switch to local mode
245
- * @see https://community.arm.com/graphics/b/blog/posts/reflections-based-on-local-cubemaps-in-unity
246
- * @example https://www.babylonjs-playground.com/#RNASML
247
- */
248
- set boundingBoxSize(value) {
249
- if (this._boundingBoxSize && this._boundingBoxSize.equals(value)) {
250
- return;
251
- }
252
- this._boundingBoxSize = value;
253
- const scene = this.getScene();
254
- if (scene) {
255
- scene.markAllMaterialsAsDirty(1);
256
- }
257
- }
258
- /**
259
- * Returns the bounding box size
260
- * @see https://doc.babylonjs.com/features/featuresDeepDive/materials/using/reflectionTexture#using-local-cubemap-mode
261
- */
262
- get boundingBoxSize() {
263
- return this._boundingBoxSize;
264
- }
265
- /**
266
- * Sets texture matrix rotation angle around Y axis in radians.
267
- */
268
- set rotationY(value) {
269
- this._rotationY = value;
270
- this.setReflectionTextureMatrix(Matrix.RotationY(this._rotationY));
271
- }
272
- /**
273
- * Gets texture matrix rotation angle around Y axis radians.
274
- */
275
- get rotationY() {
276
- return this._rotationY;
277
- }
278
- /**
279
- * Are mip maps generated for this texture or not.
280
- */
281
- get noMipmap() {
282
- return this._noMipmap;
283
- }
284
- /**
285
- * Gets the forced extension (if any)
286
- */
287
- get forcedExtension() {
288
- return this._forcedExtension;
289
- }
290
- /**
291
- * Creates a cube texture from an array of image urls
292
- * @param files defines an array of image urls
293
- * @param scene defines the hosting scene
294
- * @param noMipmap specifies if mip maps are not used
295
- * @returns a cube texture
296
- */
297
- static CreateFromImages(files, scene, noMipmap) {
298
- let rootUrlKey = "";
299
- files.forEach((url) => (rootUrlKey += url));
300
- return new CubeTexture(rootUrlKey, scene, null, noMipmap, files);
301
- }
302
- /**
303
- * Creates and return a texture created from prefilterd data by tools like IBL Baker or Lys.
304
- * @param url defines the url of the prefiltered texture
305
- * @param scene defines the scene the texture is attached to
306
- * @param forcedExtension defines the extension of the file if different from the url
307
- * @param createPolynomials defines whether or not to create polynomial harmonics from the texture data if necessary
308
- * @returns the prefiltered texture
309
- */
310
- static CreateFromPrefilteredData(url, scene, forcedExtension = null, createPolynomials = true) {
311
- const oldValue = scene.useDelayedTextureLoading;
312
- scene.useDelayedTextureLoading = false;
313
- const result = new CubeTexture(url, scene, null, false, null, null, null, undefined, true, forcedExtension, createPolynomials);
314
- scene.useDelayedTextureLoading = oldValue;
315
- return result;
316
- }
317
- /**
318
- * Creates a cube texture to use with reflection for instance. It can be based upon dds or six images as well
319
- * as prefiltered data.
320
- * @param rootUrl defines the url of the texture or the root name of the six images
321
- * @param sceneOrEngine defines the scene or engine the texture is attached to
322
- * @param extensions defines the suffixes add to the picture name in case six images are in use like _px.jpg...
323
- * @param noMipmap defines if mipmaps should be created or not
324
- * @param files defines the six files to load for the different faces in that order: px, py, pz, nx, ny, nz
325
- * @param onLoad defines a callback triggered at the end of the file load if no errors occurred
326
- * @param onError defines a callback triggered in case of error during load
327
- * @param format defines the internal format to use for the texture once loaded
328
- * @param prefiltered defines whether or not the texture is created from prefiltered data
329
- * @param forcedExtension defines the extensions to use (force a special type of file to load) in case it is different from the file name
330
- * @param createPolynomials defines whether or not to create polynomial harmonics from the texture data if necessary
331
- * @param lodScale defines the scale applied to environment texture. This manages the range of LOD level used for IBL according to the roughness
332
- * @param lodOffset defines the offset applied to environment texture. This manages first LOD level used for IBL according to the roughness
333
- * @param loaderOptions options to be passed to the loader
334
- * @param useSRGBBuffer Defines if the texture must be loaded in a sRGB GPU buffer (if supported by the GPU) (default: false)
335
- * @returns the cube texture
336
- */
337
- constructor(rootUrl, sceneOrEngine, extensions = null, noMipmap = false, files = null, onLoad = null, onError = null, format = 5, prefiltered = false, forcedExtension = null, createPolynomials = false, lodScale = 0.8, lodOffset = 0, loaderOptions, useSRGBBuffer) {
338
- var _a;
339
- super(sceneOrEngine);
340
- this._lodScale = 0.8;
341
- this._lodOffset = 0;
342
- /**
343
- * Observable triggered once the texture has been loaded.
344
- */
345
- this.onLoadObservable = new Observable();
346
- /**
347
- * Gets or sets the center of the bounding box associated with the cube texture.
348
- * It must define where the camera used to render the texture was set
349
- * @see https://doc.babylonjs.com/features/featuresDeepDive/materials/using/reflectionTexture#using-local-cubemap-mode
350
- */
351
- this.boundingBoxPosition = Vector3.Zero();
352
- this._rotationY = 0;
353
- /** @internal */
354
- this._files = null;
355
- this._forcedExtension = null;
356
- this._extensions = null;
357
- this._textureMatrixRefraction = new Matrix();
358
- this.name = rootUrl;
359
- this.url = rootUrl;
360
- this._noMipmap = noMipmap;
361
- this.hasAlpha = false;
362
- this._format = format;
363
- this.isCube = true;
364
- this._textureMatrix = Matrix.Identity();
365
- this._createPolynomials = createPolynomials;
366
- this.coordinatesMode = Texture.CUBIC_MODE;
367
- this._extensions = extensions;
368
- this._files = files;
369
- this._forcedExtension = forcedExtension;
370
- this._loaderOptions = loaderOptions;
371
- this._useSRGBBuffer = useSRGBBuffer;
372
- this._lodScale = lodScale;
373
- this._lodOffset = lodOffset;
374
- if (!rootUrl && !files) {
375
- return;
376
- }
377
- this.updateURL(rootUrl, forcedExtension, onLoad, prefiltered, onError, extensions, (_a = this.getScene()) === null || _a === void 0 ? void 0 : _a.useDelayedTextureLoading, files);
378
- }
379
- /**
380
- * Get the current class name of the texture useful for serialization or dynamic coding.
381
- * @returns "CubeTexture"
382
- */
383
- getClassName() {
384
- return "CubeTexture";
385
- }
386
- /**
387
- * Update the url (and optional buffer) of this texture if url was null during construction.
388
- * @param url the url of the texture
389
- * @param forcedExtension defines the extension to use
390
- * @param onLoad callback called when the texture is loaded (defaults to null)
391
- * @param prefiltered Defines whether the updated texture is prefiltered or not
392
- * @param onError callback called if there was an error during the loading process (defaults to null)
393
- * @param extensions defines the suffixes add to the picture name in case six images are in use like _px.jpg...
394
- * @param delayLoad defines if the texture should be loaded now (false by default)
395
- * @param files defines the six files to load for the different faces in that order: px, py, pz, nx, ny, nz
396
- */
397
- updateURL(url, forcedExtension, onLoad = null, prefiltered = false, onError = null, extensions = null, delayLoad = false, files = null) {
398
- if (!this.name || this.name.startsWith("data:")) {
399
- this.name = url;
400
- }
401
- this.url = url;
402
- if (forcedExtension) {
403
- this._forcedExtension = forcedExtension;
404
- }
405
- const lastDot = url.lastIndexOf(".");
406
- const extension = forcedExtension ? forcedExtension : lastDot > -1 ? url.substring(lastDot).toLowerCase() : "";
407
- const isDDS = extension.indexOf(".dds") === 0;
408
- const isEnv = extension.indexOf(".env") === 0;
409
- const isBasis = extension.indexOf(".basis") === 0;
410
- if (isEnv) {
411
- this.gammaSpace = false;
412
- this._prefiltered = false;
413
- this.anisotropicFilteringLevel = 1;
414
- }
415
- else {
416
- this._prefiltered = prefiltered;
417
- if (prefiltered) {
418
- this.gammaSpace = false;
419
- this.anisotropicFilteringLevel = 1;
420
- }
421
- }
422
- if (files) {
423
- this._files = files;
424
- }
425
- else {
426
- if (!isBasis && !isEnv && !isDDS && !extensions) {
427
- extensions = ["_px.jpg", "_py.jpg", "_pz.jpg", "_nx.jpg", "_ny.jpg", "_nz.jpg"];
428
- }
429
- this._files = this._files || [];
430
- this._files.length = 0;
431
- if (extensions) {
432
- for (let index = 0; index < extensions.length; index++) {
433
- this._files.push(url + extensions[index]);
434
- }
435
- this._extensions = extensions;
436
- }
437
- }
438
- if (delayLoad) {
439
- this.delayLoadState = 4;
440
- this._delayedOnLoad = onLoad;
441
- this._delayedOnError = onError;
442
- }
443
- else {
444
- this._loadTexture(onLoad, onError);
445
- }
446
- }
447
- /**
448
- * Delays loading of the cube texture
449
- * @param forcedExtension defines the extension to use
450
- */
451
- delayLoad(forcedExtension) {
452
- if (this.delayLoadState !== 4) {
453
- return;
454
- }
455
- if (forcedExtension) {
456
- this._forcedExtension = forcedExtension;
457
- }
458
- this.delayLoadState = 1;
459
- this._loadTexture(this._delayedOnLoad, this._delayedOnError);
460
- }
461
- /**
462
- * Returns the reflection texture matrix
463
- * @returns the reflection texture matrix
464
- */
465
- getReflectionTextureMatrix() {
466
- return this._textureMatrix;
467
- }
468
- /**
469
- * Sets the reflection texture matrix
470
- * @param value Reflection texture matrix
471
- */
472
- setReflectionTextureMatrix(value) {
473
- var _a, _b;
474
- if (value.updateFlag === this._textureMatrix.updateFlag) {
475
- return;
476
- }
477
- if (value.isIdentity() !== this._textureMatrix.isIdentity()) {
478
- (_a = this.getScene()) === null || _a === void 0 ? void 0 : _a.markAllMaterialsAsDirty(1, (mat) => mat.getActiveTextures().indexOf(this) !== -1);
479
- }
480
- this._textureMatrix = value;
481
- if (!((_b = this.getScene()) === null || _b === void 0 ? void 0 : _b.useRightHandedSystem)) {
482
- return;
483
- }
484
- const scale = TmpVectors.Vector3[0];
485
- const quat = TmpVectors.Quaternion[0];
486
- const trans = TmpVectors.Vector3[1];
487
- this._textureMatrix.decompose(scale, quat, trans);
488
- quat.z *= -1; // these two operations correspond to negating the x and y euler angles
489
- quat.w *= -1;
490
- Matrix.ComposeToRef(scale, quat, trans, this._textureMatrixRefraction);
491
- }
492
- /**
493
- * Gets a suitable rotate/transform matrix when the texture is used for refraction.
494
- * There's a separate function from getReflectionTextureMatrix because refraction requires a special configuration of the matrix in right-handed mode.
495
- * @returns The refraction matrix
496
- */
497
- getRefractionTextureMatrix() {
498
- var _a;
499
- return ((_a = this.getScene()) === null || _a === void 0 ? void 0 : _a.useRightHandedSystem) ? this._textureMatrixRefraction : this._textureMatrix;
500
- }
501
- _loadTexture(onLoad = null, onError = null) {
502
- var _a;
503
- const scene = this.getScene();
504
- const oldTexture = this._texture;
505
- this._texture = this._getFromCache(this.url, this._noMipmap, undefined, undefined, this._useSRGBBuffer, this.isCube);
506
- const onLoadProcessing = () => {
507
- var _a;
508
- this.onLoadObservable.notifyObservers(this);
509
- if (oldTexture) {
510
- oldTexture.dispose();
511
- (_a = this.getScene()) === null || _a === void 0 ? void 0 : _a.markAllMaterialsAsDirty(1);
512
- }
513
- if (onLoad) {
514
- onLoad();
515
- }
516
- };
517
- const errorHandler = (message, exception) => {
518
- this._loadingError = true;
519
- this._errorObject = { message, exception };
520
- if (onError) {
521
- onError(message, exception);
522
- }
523
- Texture.OnTextureLoadErrorObservable.notifyObservers(this);
524
- };
525
- if (!this._texture) {
526
- if (this._prefiltered) {
527
- this._texture = this._getEngine().createPrefilteredCubeTexture(this.url, scene, this._lodScale, this._lodOffset, onLoad, errorHandler, this._format, this._forcedExtension, this._createPolynomials);
528
- }
529
- else {
530
- this._texture = this._getEngine().createCubeTexture(this.url, scene, this._files, this._noMipmap, onLoad, errorHandler, this._format, this._forcedExtension, false, this._lodScale, this._lodOffset, null, this._loaderOptions, !!this._useSRGBBuffer);
531
- }
532
- (_a = this._texture) === null || _a === void 0 ? void 0 : _a.onLoadedObservable.add(() => this.onLoadObservable.notifyObservers(this));
533
- }
534
- else {
535
- if (this._texture.isReady) {
536
- Tools.SetImmediate(() => onLoadProcessing());
537
- }
538
- else {
539
- this._texture.onLoadedObservable.add(() => onLoadProcessing());
540
- }
541
- }
542
- }
543
- /**
544
- * Parses text to create a cube texture
545
- * @param parsedTexture define the serialized text to read from
546
- * @param scene defines the hosting scene
547
- * @param rootUrl defines the root url of the cube texture
548
- * @returns a cube texture
549
- */
550
- static Parse(parsedTexture, scene, rootUrl) {
551
- const texture = SerializationHelper.Parse(() => {
552
- var _a;
553
- let prefiltered = false;
554
- if (parsedTexture.prefiltered) {
555
- prefiltered = parsedTexture.prefiltered;
556
- }
557
- return new CubeTexture(rootUrl + ((_a = parsedTexture.url) !== null && _a !== void 0 ? _a : parsedTexture.name), scene, parsedTexture.extensions, false, parsedTexture.files || null, null, null, undefined, prefiltered, parsedTexture.forcedExtension);
558
- }, parsedTexture, scene);
559
- // Local Cubemaps
560
- if (parsedTexture.boundingBoxPosition) {
561
- texture.boundingBoxPosition = Vector3.FromArray(parsedTexture.boundingBoxPosition);
562
- }
563
- if (parsedTexture.boundingBoxSize) {
564
- texture.boundingBoxSize = Vector3.FromArray(parsedTexture.boundingBoxSize);
565
- }
566
- // Animations
567
- if (parsedTexture.animations) {
568
- for (let animationIndex = 0; animationIndex < parsedTexture.animations.length; animationIndex++) {
569
- const parsedAnimation = parsedTexture.animations[animationIndex];
570
- const internalClass = GetClass("BABYLON.Animation");
571
- if (internalClass) {
572
- texture.animations.push(internalClass.Parse(parsedAnimation));
573
- }
574
- }
575
- }
576
- return texture;
577
- }
578
- /**
579
- * Makes a clone, or deep copy, of the cube texture
580
- * @returns a new cube texture
581
- */
582
- clone() {
583
- let uniqueId = 0;
584
- const newCubeTexture = SerializationHelper.Clone(() => {
585
- const cubeTexture = new CubeTexture(this.url, this.getScene() || this._getEngine(), this._extensions, this._noMipmap, this._files);
586
- uniqueId = cubeTexture.uniqueId;
587
- return cubeTexture;
588
- }, this);
589
- newCubeTexture.uniqueId = uniqueId;
590
- return newCubeTexture;
591
- }
592
- }
593
- __decorate([
594
- serialize()
595
- ], CubeTexture.prototype, "url", void 0);
596
- __decorate([
597
- serializeAsVector3()
598
- ], CubeTexture.prototype, "boundingBoxPosition", void 0);
599
- __decorate([
600
- serializeAsVector3()
601
- ], CubeTexture.prototype, "boundingBoxSize", null);
602
- __decorate([
603
- serialize("rotationY")
604
- ], CubeTexture.prototype, "rotationY", null);
605
- __decorate([
606
- serialize("files")
607
- ], CubeTexture.prototype, "_files", void 0);
608
- __decorate([
609
- serialize("forcedExtension")
610
- ], CubeTexture.prototype, "_forcedExtension", void 0);
611
- __decorate([
612
- serialize("extensions")
613
- ], CubeTexture.prototype, "_extensions", void 0);
614
- __decorate([
615
- serializeAsMatrix("textureMatrix")
616
- ], CubeTexture.prototype, "_textureMatrix", void 0);
617
- __decorate([
618
- serializeAsMatrix("textureMatrixRefraction")
619
- ], CubeTexture.prototype, "_textureMatrixRefraction", void 0);
620
- Texture._CubeTextureParser = CubeTexture.Parse;
621
- // Some exporters relies on Tools.Instantiate
622
- RegisterClass("BABYLON.CubeTexture", CubeTexture);
623
-
624
- ThinEngine.prototype.updateRawTexture = function (texture, data, format, invertY, compression = null, type = 0, useSRGBBuffer = false) {
625
- if (!texture) {
626
- return;
627
- }
628
- // Babylon's internalSizedFomat but gl's texImage2D internalFormat
629
- const internalSizedFomat = this._getRGBABufferInternalSizedFormat(type, format, useSRGBBuffer);
630
- // Babylon's internalFormat but gl's texImage2D format
631
- const internalFormat = this._getInternalFormat(format);
632
- const textureType = this._getWebGLTextureType(type);
633
- this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
634
- this._unpackFlipY(invertY === undefined ? true : invertY ? true : false);
635
- if (!this._doNotHandleContextLost) {
636
- texture._bufferView = data;
637
- texture.format = format;
638
- texture.type = type;
639
- texture.invertY = invertY;
640
- texture._compression = compression;
641
- }
642
- if (texture.width % 4 !== 0) {
643
- this._gl.pixelStorei(this._gl.UNPACK_ALIGNMENT, 1);
644
- }
645
- if (compression && data) {
646
- this._gl.compressedTexImage2D(this._gl.TEXTURE_2D, 0, this.getCaps().s3tc[compression], texture.width, texture.height, 0, data);
647
- }
648
- else {
649
- this._gl.texImage2D(this._gl.TEXTURE_2D, 0, internalSizedFomat, texture.width, texture.height, 0, internalFormat, textureType, data);
650
- }
651
- if (texture.generateMipMaps) {
652
- this._gl.generateMipmap(this._gl.TEXTURE_2D);
653
- }
654
- this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
655
- // this.resetTextureCache();
656
- texture.isReady = true;
657
- };
658
- ThinEngine.prototype.createRawTexture = function (data, width, height, format, generateMipMaps, invertY, samplingMode, compression = null, type = 0,
659
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
660
- creationFlags = 0, useSRGBBuffer = false) {
661
- const texture = new InternalTexture(this, InternalTextureSource.Raw);
662
- texture.baseWidth = width;
663
- texture.baseHeight = height;
664
- texture.width = width;
665
- texture.height = height;
666
- texture.format = format;
667
- texture.generateMipMaps = generateMipMaps;
668
- texture.samplingMode = samplingMode;
669
- texture.invertY = invertY;
670
- texture._compression = compression;
671
- texture.type = type;
672
- texture._useSRGBBuffer = this._getUseSRGBBuffer(useSRGBBuffer, !generateMipMaps);
673
- if (!this._doNotHandleContextLost) {
674
- texture._bufferView = data;
675
- }
676
- this.updateRawTexture(texture, data, format, invertY, compression, type, texture._useSRGBBuffer);
677
- this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
678
- // Filters
679
- const filters = this._getSamplingParameters(samplingMode, generateMipMaps);
680
- this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER, filters.mag);
681
- this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, filters.min);
682
- if (generateMipMaps) {
683
- this._gl.generateMipmap(this._gl.TEXTURE_2D);
684
- }
685
- this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
686
- this._internalTexturesCache.push(texture);
687
- return texture;
688
- };
689
- ThinEngine.prototype.createRawCubeTexture = function (data, size, format, type, generateMipMaps, invertY, samplingMode, compression = null) {
690
- const gl = this._gl;
691
- const texture = new InternalTexture(this, InternalTextureSource.CubeRaw);
692
- texture.isCube = true;
693
- texture.format = format;
694
- texture.type = type;
695
- if (!this._doNotHandleContextLost) {
696
- texture._bufferViewArray = data;
697
- }
698
- const textureType = this._getWebGLTextureType(type);
699
- let internalFormat = this._getInternalFormat(format);
700
- if (internalFormat === gl.RGB) {
701
- internalFormat = gl.RGBA;
702
- }
703
- // Mipmap generation needs a sized internal format that is both color-renderable and texture-filterable
704
- if (textureType === gl.FLOAT && !this._caps.textureFloatLinearFiltering) {
705
- generateMipMaps = false;
706
- samplingMode = 1;
707
- Logger.Warn("Float texture filtering is not supported. Mipmap generation and sampling mode are forced to false and TEXTURE_NEAREST_SAMPLINGMODE, respectively.");
708
- }
709
- else if (textureType === this._gl.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
710
- generateMipMaps = false;
711
- samplingMode = 1;
712
- Logger.Warn("Half float texture filtering is not supported. Mipmap generation and sampling mode are forced to false and TEXTURE_NEAREST_SAMPLINGMODE, respectively.");
713
- }
714
- else if (textureType === gl.FLOAT && !this._caps.textureFloatRender) {
715
- generateMipMaps = false;
716
- Logger.Warn("Render to float textures is not supported. Mipmap generation forced to false.");
717
- }
718
- else if (textureType === gl.HALF_FLOAT && !this._caps.colorBufferFloat) {
719
- generateMipMaps = false;
720
- Logger.Warn("Render to half float textures is not supported. Mipmap generation forced to false.");
721
- }
722
- const width = size;
723
- const height = width;
724
- texture.width = width;
725
- texture.height = height;
726
- texture.invertY = invertY;
727
- texture._compression = compression;
728
- // Double check on POT to generate Mips.
729
- const isPot = !this.needPOTTextures || (Tools.IsExponentOfTwo(texture.width) && Tools.IsExponentOfTwo(texture.height));
730
- if (!isPot) {
731
- generateMipMaps = false;
732
- }
733
- // Upload data if needed. The texture won't be ready until then.
734
- if (data) {
735
- this.updateRawCubeTexture(texture, data, format, type, invertY, compression);
736
- }
737
- else {
738
- const internalSizedFomat = this._getRGBABufferInternalSizedFormat(type);
739
- const level = 0;
740
- this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
741
- for (let faceIndex = 0; faceIndex < 6; faceIndex++) {
742
- if (compression) {
743
- gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, this.getCaps().s3tc[compression], texture.width, texture.height, 0, undefined);
744
- }
745
- else {
746
- gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, internalSizedFomat, texture.width, texture.height, 0, internalFormat, textureType, null);
747
- }
748
- }
749
- this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
750
- }
751
- this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, texture, true);
752
- // Filters
753
- if (data && generateMipMaps) {
754
- this._gl.generateMipmap(this._gl.TEXTURE_CUBE_MAP);
755
- }
756
- const filters = this._getSamplingParameters(samplingMode, generateMipMaps);
757
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, filters.mag);
758
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, filters.min);
759
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
760
- gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
761
- this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
762
- texture.generateMipMaps = generateMipMaps;
763
- texture.samplingMode = samplingMode;
764
- texture.isReady = true;
765
- return texture;
766
- };
767
- ThinEngine.prototype.updateRawCubeTexture = function (texture, data, format, type, invertY, compression = null, level = 0) {
768
- texture._bufferViewArray = data;
769
- texture.format = format;
770
- texture.type = type;
771
- texture.invertY = invertY;
772
- texture._compression = compression;
773
- const gl = this._gl;
774
- const textureType = this._getWebGLTextureType(type);
775
- let internalFormat = this._getInternalFormat(format);
776
- const internalSizedFomat = this._getRGBABufferInternalSizedFormat(type);
777
- let needConversion = false;
778
- if (internalFormat === gl.RGB) {
779
- internalFormat = gl.RGBA;
780
- needConversion = true;
781
- }
782
- this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
783
- this._unpackFlipY(invertY === undefined ? true : invertY ? true : false);
784
- if (texture.width % 4 !== 0) {
785
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
786
- }
787
- // Data are known to be in +X +Y +Z -X -Y -Z
788
- for (let faceIndex = 0; faceIndex < 6; faceIndex++) {
789
- let faceData = data[faceIndex];
790
- if (compression) {
791
- gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, this.getCaps().s3tc[compression], texture.width, texture.height, 0, faceData);
792
- }
793
- else {
794
- if (needConversion) {
795
- faceData = _convertRGBtoRGBATextureData(faceData, texture.width, texture.height, type);
796
- }
797
- gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, internalSizedFomat, texture.width, texture.height, 0, internalFormat, textureType, faceData);
798
- }
799
- }
800
- const isPot = !this.needPOTTextures || (Tools.IsExponentOfTwo(texture.width) && Tools.IsExponentOfTwo(texture.height));
801
- if (isPot && texture.generateMipMaps && level === 0) {
802
- this._gl.generateMipmap(this._gl.TEXTURE_CUBE_MAP);
803
- }
804
- this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
805
- // this.resetTextureCache();
806
- texture.isReady = true;
807
- };
808
- ThinEngine.prototype.createRawCubeTextureFromUrl = function (url, scene, size, format, type, noMipmap, callback, mipmapGenerator, onLoad = null, onError = null, samplingMode = 3, invertY = false) {
809
- const gl = this._gl;
810
- const texture = this.createRawCubeTexture(null, size, format, type, !noMipmap, invertY, samplingMode, null);
811
- scene === null || scene === void 0 ? void 0 : scene.addPendingData(texture);
812
- texture.url = url;
813
- texture.isReady = false;
814
- this._internalTexturesCache.push(texture);
815
- const onerror = (request, exception) => {
816
- scene === null || scene === void 0 ? void 0 : scene.removePendingData(texture);
817
- if (onError && request) {
818
- onError(request.status + " " + request.statusText, exception);
819
- }
820
- };
821
- const internalCallback = (data) => {
822
- const width = texture.width;
823
- const faceDataArrays = callback(data);
824
- if (!faceDataArrays) {
825
- return;
826
- }
827
- if (mipmapGenerator) {
828
- const textureType = this._getWebGLTextureType(type);
829
- let internalFormat = this._getInternalFormat(format);
830
- const internalSizedFomat = this._getRGBABufferInternalSizedFormat(type);
831
- let needConversion = false;
832
- if (internalFormat === gl.RGB) {
833
- internalFormat = gl.RGBA;
834
- needConversion = true;
835
- }
836
- this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
837
- this._unpackFlipY(false);
838
- const mipData = mipmapGenerator(faceDataArrays);
839
- for (let level = 0; level < mipData.length; level++) {
840
- const mipSize = width >> level;
841
- for (let faceIndex = 0; faceIndex < 6; faceIndex++) {
842
- let mipFaceData = mipData[level][faceIndex];
843
- if (needConversion) {
844
- mipFaceData = _convertRGBtoRGBATextureData(mipFaceData, mipSize, mipSize, type);
845
- }
846
- gl.texImage2D(faceIndex, level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipFaceData);
847
- }
848
- }
849
- this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
850
- }
851
- else {
852
- this.updateRawCubeTexture(texture, faceDataArrays, format, type, invertY);
853
- }
854
- texture.isReady = true;
855
- // this.resetTextureCache();
856
- scene === null || scene === void 0 ? void 0 : scene.removePendingData(texture);
857
- texture.onLoadedObservable.notifyObservers(texture);
858
- texture.onLoadedObservable.clear();
859
- if (onLoad) {
860
- onLoad();
861
- }
862
- };
863
- this._loadFile(url, (data) => {
864
- internalCallback(data);
865
- }, undefined, scene === null || scene === void 0 ? void 0 : scene.offlineProvider, true, onerror);
866
- return texture;
867
- };
868
- /**
869
- * @internal
870
- */
871
- // eslint-disable-next-line @typescript-eslint/naming-convention
872
- function _convertRGBtoRGBATextureData(rgbData, width, height, textureType) {
873
- // Create new RGBA data container.
874
- let rgbaData;
875
- let val1 = 1;
876
- if (textureType === 1) {
877
- rgbaData = new Float32Array(width * height * 4);
878
- }
879
- else if (textureType === 2) {
880
- rgbaData = new Uint16Array(width * height * 4);
881
- val1 = 15360; // 15360 is the encoding of 1 in half float
882
- }
883
- else if (textureType === 7) {
884
- rgbaData = new Uint32Array(width * height * 4);
885
- }
886
- else {
887
- rgbaData = new Uint8Array(width * height * 4);
888
- }
889
- // Convert each pixel.
890
- for (let x = 0; x < width; x++) {
891
- for (let y = 0; y < height; y++) {
892
- const index = (y * width + x) * 3;
893
- const newIndex = (y * width + x) * 4;
894
- // Map Old Value to new value.
895
- rgbaData[newIndex + 0] = rgbData[index + 0];
896
- rgbaData[newIndex + 1] = rgbData[index + 1];
897
- rgbaData[newIndex + 2] = rgbData[index + 2];
898
- // Add fully opaque alpha channel.
899
- rgbaData[newIndex + 3] = val1;
900
- }
901
- }
902
- return rgbaData;
903
- }
904
- /**
905
- * Create a function for createRawTexture3D/createRawTexture2DArray
906
- * @param is3D true for TEXTURE_3D and false for TEXTURE_2D_ARRAY
907
- * @internal
908
- */
909
- // eslint-disable-next-line @typescript-eslint/naming-convention
910
- function _makeCreateRawTextureFunction(is3D) {
911
- return function (data, width, height, depth, format, generateMipMaps, invertY, samplingMode, compression = null, textureType = 0) {
912
- const target = is3D ? this._gl.TEXTURE_3D : this._gl.TEXTURE_2D_ARRAY;
913
- const source = is3D ? InternalTextureSource.Raw3D : InternalTextureSource.Raw2DArray;
914
- const texture = new InternalTexture(this, source);
915
- texture.baseWidth = width;
916
- texture.baseHeight = height;
917
- texture.baseDepth = depth;
918
- texture.width = width;
919
- texture.height = height;
920
- texture.depth = depth;
921
- texture.format = format;
922
- texture.type = textureType;
923
- texture.generateMipMaps = generateMipMaps;
924
- texture.samplingMode = samplingMode;
925
- if (is3D) {
926
- texture.is3D = true;
927
- }
928
- else {
929
- texture.is2DArray = true;
930
- }
931
- if (!this._doNotHandleContextLost) {
932
- texture._bufferView = data;
933
- }
934
- if (is3D) {
935
- this.updateRawTexture3D(texture, data, format, invertY, compression, textureType);
936
- }
937
- else {
938
- this.updateRawTexture2DArray(texture, data, format, invertY, compression, textureType);
939
- }
940
- this._bindTextureDirectly(target, texture, true);
941
- // Filters
942
- const filters = this._getSamplingParameters(samplingMode, generateMipMaps);
943
- this._gl.texParameteri(target, this._gl.TEXTURE_MAG_FILTER, filters.mag);
944
- this._gl.texParameteri(target, this._gl.TEXTURE_MIN_FILTER, filters.min);
945
- if (generateMipMaps) {
946
- this._gl.generateMipmap(target);
947
- }
948
- this._bindTextureDirectly(target, null);
949
- this._internalTexturesCache.push(texture);
950
- return texture;
951
- };
952
- }
953
- ThinEngine.prototype.createRawTexture2DArray = _makeCreateRawTextureFunction(false);
954
- ThinEngine.prototype.createRawTexture3D = _makeCreateRawTextureFunction(true);
955
- /**
956
- * Create a function for updateRawTexture3D/updateRawTexture2DArray
957
- * @param is3D true for TEXTURE_3D and false for TEXTURE_2D_ARRAY
958
- * @internal
959
- */
960
- // eslint-disable-next-line @typescript-eslint/naming-convention
961
- function _makeUpdateRawTextureFunction(is3D) {
962
- return function (texture, data, format, invertY, compression = null, textureType = 0) {
963
- const target = is3D ? this._gl.TEXTURE_3D : this._gl.TEXTURE_2D_ARRAY;
964
- const internalType = this._getWebGLTextureType(textureType);
965
- const internalFormat = this._getInternalFormat(format);
966
- const internalSizedFomat = this._getRGBABufferInternalSizedFormat(textureType, format);
967
- this._bindTextureDirectly(target, texture, true);
968
- this._unpackFlipY(invertY === undefined ? true : invertY ? true : false);
969
- if (!this._doNotHandleContextLost) {
970
- texture._bufferView = data;
971
- texture.format = format;
972
- texture.invertY = invertY;
973
- texture._compression = compression;
974
- }
975
- if (texture.width % 4 !== 0) {
976
- this._gl.pixelStorei(this._gl.UNPACK_ALIGNMENT, 1);
977
- }
978
- if (compression && data) {
979
- this._gl.compressedTexImage3D(target, 0, this.getCaps().s3tc[compression], texture.width, texture.height, texture.depth, 0, data);
980
- }
981
- else {
982
- this._gl.texImage3D(target, 0, internalSizedFomat, texture.width, texture.height, texture.depth, 0, internalFormat, internalType, data);
983
- }
984
- if (texture.generateMipMaps) {
985
- this._gl.generateMipmap(target);
986
- }
987
- this._bindTextureDirectly(target, null);
988
- // this.resetTextureCache();
989
- texture.isReady = true;
990
- };
991
- }
992
- ThinEngine.prototype.updateRawTexture2DArray = _makeUpdateRawTextureFunction(false);
993
- ThinEngine.prototype.updateRawTexture3D = _makeUpdateRawTextureFunction(true);
994
-
995
- /**
996
- * Helper class useful to convert panorama picture to their cubemap representation in 6 faces.
997
- */
998
- class PanoramaToCubeMapTools {
999
- /**
1000
- * Converts a panorama stored in RGB right to left up to down format into a cubemap (6 faces).
1001
- *
1002
- * @param float32Array The source data.
1003
- * @param inputWidth The width of the input panorama.
1004
- * @param inputHeight The height of the input panorama.
1005
- * @param size The willing size of the generated cubemap (each faces will be size * size pixels)
1006
- * @returns The cubemap data
1007
- */
1008
- static ConvertPanoramaToCubemap(float32Array, inputWidth, inputHeight, size, supersample = false) {
1009
- if (!float32Array) {
1010
- throw "ConvertPanoramaToCubemap: input cannot be null";
1011
- }
1012
- if (float32Array.length != inputWidth * inputHeight * 3) {
1013
- throw "ConvertPanoramaToCubemap: input size is wrong";
1014
- }
1015
- const textureFront = this.CreateCubemapTexture(size, this.FACE_FRONT, float32Array, inputWidth, inputHeight, supersample);
1016
- const textureBack = this.CreateCubemapTexture(size, this.FACE_BACK, float32Array, inputWidth, inputHeight, supersample);
1017
- const textureLeft = this.CreateCubemapTexture(size, this.FACE_LEFT, float32Array, inputWidth, inputHeight, supersample);
1018
- const textureRight = this.CreateCubemapTexture(size, this.FACE_RIGHT, float32Array, inputWidth, inputHeight, supersample);
1019
- const textureUp = this.CreateCubemapTexture(size, this.FACE_UP, float32Array, inputWidth, inputHeight, supersample);
1020
- const textureDown = this.CreateCubemapTexture(size, this.FACE_DOWN, float32Array, inputWidth, inputHeight, supersample);
1021
- return {
1022
- front: textureFront,
1023
- back: textureBack,
1024
- left: textureLeft,
1025
- right: textureRight,
1026
- up: textureUp,
1027
- down: textureDown,
1028
- size: size,
1029
- type: 1,
1030
- format: 4,
1031
- gammaSpace: false,
1032
- };
1033
- }
1034
- static CreateCubemapTexture(texSize, faceData, float32Array, inputWidth, inputHeight, supersample = false) {
1035
- const buffer = new ArrayBuffer(texSize * texSize * 4 * 3);
1036
- const textureArray = new Float32Array(buffer);
1037
- // If supersampling, determine number of samples needed when source texture width is divided for 4 cube faces
1038
- const samples = supersample ? Math.max(1, Math.round(inputWidth / 4 / texSize)) : 1;
1039
- const sampleFactor = 1 / samples;
1040
- const sampleFactorSqr = sampleFactor * sampleFactor;
1041
- const rotDX1 = faceData[1].subtract(faceData[0]).scale(sampleFactor / texSize);
1042
- const rotDX2 = faceData[3].subtract(faceData[2]).scale(sampleFactor / texSize);
1043
- const dy = 1 / texSize;
1044
- let fy = 0;
1045
- for (let y = 0; y < texSize; y++) {
1046
- for (let sy = 0; sy < samples; sy++) {
1047
- let xv1 = faceData[0];
1048
- let xv2 = faceData[2];
1049
- for (let x = 0; x < texSize; x++) {
1050
- for (let sx = 0; sx < samples; sx++) {
1051
- const v = xv2.subtract(xv1).scale(fy).add(xv1);
1052
- v.normalize();
1053
- const color = this.CalcProjectionSpherical(v, float32Array, inputWidth, inputHeight);
1054
- // 3 channels per pixels
1055
- textureArray[y * texSize * 3 + x * 3 + 0] += color.r * sampleFactorSqr;
1056
- textureArray[y * texSize * 3 + x * 3 + 1] += color.g * sampleFactorSqr;
1057
- textureArray[y * texSize * 3 + x * 3 + 2] += color.b * sampleFactorSqr;
1058
- xv1 = xv1.add(rotDX1);
1059
- xv2 = xv2.add(rotDX2);
1060
- }
1061
- }
1062
- fy += dy * sampleFactor;
1063
- }
1064
- }
1065
- return textureArray;
1066
- }
1067
- static CalcProjectionSpherical(vDir, float32Array, inputWidth, inputHeight) {
1068
- let theta = Math.atan2(vDir.z, vDir.x);
1069
- const phi = Math.acos(vDir.y);
1070
- while (theta < -Math.PI) {
1071
- theta += 2 * Math.PI;
1072
- }
1073
- while (theta > Math.PI) {
1074
- theta -= 2 * Math.PI;
1075
- }
1076
- let dx = theta / Math.PI;
1077
- const dy = phi / Math.PI;
1078
- // recenter.
1079
- dx = dx * 0.5 + 0.5;
1080
- let px = Math.round(dx * inputWidth);
1081
- if (px < 0) {
1082
- px = 0;
1083
- }
1084
- else if (px >= inputWidth) {
1085
- px = inputWidth - 1;
1086
- }
1087
- let py = Math.round(dy * inputHeight);
1088
- if (py < 0) {
1089
- py = 0;
1090
- }
1091
- else if (py >= inputHeight) {
1092
- py = inputHeight - 1;
1093
- }
1094
- const inputY = inputHeight - py - 1;
1095
- const r = float32Array[inputY * inputWidth * 3 + px * 3 + 0];
1096
- const g = float32Array[inputY * inputWidth * 3 + px * 3 + 1];
1097
- const b = float32Array[inputY * inputWidth * 3 + px * 3 + 2];
1098
- return {
1099
- r: r,
1100
- g: g,
1101
- b: b,
1102
- };
1103
- }
1104
- }
1105
- PanoramaToCubeMapTools.FACE_LEFT = [new Vector3(-1.0, -1.0, -1.0), new Vector3(1.0, -1.0, -1.0), new Vector3(-1.0, 1.0, -1.0), new Vector3(1.0, 1.0, -1.0)];
1106
- PanoramaToCubeMapTools.FACE_RIGHT = [new Vector3(1.0, -1.0, 1.0), new Vector3(-1.0, -1.0, 1.0), new Vector3(1.0, 1.0, 1.0), new Vector3(-1.0, 1.0, 1.0)];
1107
- PanoramaToCubeMapTools.FACE_FRONT = [new Vector3(1.0, -1.0, -1.0), new Vector3(1.0, -1.0, 1.0), new Vector3(1.0, 1.0, -1.0), new Vector3(1.0, 1.0, 1.0)];
1108
- PanoramaToCubeMapTools.FACE_BACK = [new Vector3(-1.0, -1.0, 1.0), new Vector3(-1.0, -1.0, -1.0), new Vector3(-1.0, 1.0, 1.0), new Vector3(-1.0, 1.0, -1.0)];
1109
- PanoramaToCubeMapTools.FACE_DOWN = [new Vector3(1.0, 1.0, -1.0), new Vector3(1.0, 1.0, 1.0), new Vector3(-1.0, 1.0, -1.0), new Vector3(-1.0, 1.0, 1.0)];
1110
- PanoramaToCubeMapTools.FACE_UP = [new Vector3(-1.0, -1.0, -1.0), new Vector3(-1.0, -1.0, 1.0), new Vector3(1.0, -1.0, -1.0), new Vector3(1.0, -1.0, 1.0)];
1111
-
1112
- /**
1113
- * This groups tools to convert HDR texture to native colors array.
1114
- */
1115
- class HDRTools {
1116
- static _Ldexp(mantissa, exponent) {
1117
- if (exponent > 1023) {
1118
- return mantissa * Math.pow(2, 1023) * Math.pow(2, exponent - 1023);
1119
- }
1120
- if (exponent < -1074) {
1121
- return mantissa * Math.pow(2, -1074) * Math.pow(2, exponent + 1074);
1122
- }
1123
- return mantissa * Math.pow(2, exponent);
1124
- }
1125
- static _Rgbe2float(float32array, red, green, blue, exponent, index) {
1126
- if (exponent > 0) {
1127
- /*nonzero pixel*/
1128
- exponent = this._Ldexp(1.0, exponent - (128 + 8));
1129
- float32array[index + 0] = red * exponent;
1130
- float32array[index + 1] = green * exponent;
1131
- float32array[index + 2] = blue * exponent;
1132
- }
1133
- else {
1134
- float32array[index + 0] = 0;
1135
- float32array[index + 1] = 0;
1136
- float32array[index + 2] = 0;
1137
- }
1138
- }
1139
- static _ReadStringLine(uint8array, startIndex) {
1140
- let line = "";
1141
- let character = "";
1142
- for (let i = startIndex; i < uint8array.length - startIndex; i++) {
1143
- character = String.fromCharCode(uint8array[i]);
1144
- if (character == "\n") {
1145
- break;
1146
- }
1147
- line += character;
1148
- }
1149
- return line;
1150
- }
1151
- /**
1152
- * Reads header information from an RGBE texture stored in a native array.
1153
- * More information on this format are available here:
1154
- * https://en.wikipedia.org/wiki/RGBE_image_format
1155
- *
1156
- * @param uint8array The binary file stored in native array.
1157
- * @returns The header information.
1158
- */
1159
- // eslint-disable-next-line @typescript-eslint/naming-convention
1160
- static RGBE_ReadHeader(uint8array) {
1161
- let height = 0;
1162
- let width = 0;
1163
- let line = this._ReadStringLine(uint8array, 0);
1164
- if (line[0] != "#" || line[1] != "?") {
1165
- throw "Bad HDR Format.";
1166
- }
1167
- let endOfHeader = false;
1168
- let findFormat = false;
1169
- let lineIndex = 0;
1170
- do {
1171
- lineIndex += line.length + 1;
1172
- line = this._ReadStringLine(uint8array, lineIndex);
1173
- if (line == "FORMAT=32-bit_rle_rgbe") {
1174
- findFormat = true;
1175
- }
1176
- else if (line.length == 0) {
1177
- endOfHeader = true;
1178
- }
1179
- } while (!endOfHeader);
1180
- if (!findFormat) {
1181
- throw "HDR Bad header format, unsupported FORMAT";
1182
- }
1183
- lineIndex += line.length + 1;
1184
- line = this._ReadStringLine(uint8array, lineIndex);
1185
- const sizeRegexp = /^-Y (.*) \+X (.*)$/g;
1186
- const match = sizeRegexp.exec(line);
1187
- // TODO. Support +Y and -X if needed.
1188
- if (!match || match.length < 3) {
1189
- throw "HDR Bad header format, no size";
1190
- }
1191
- width = parseInt(match[2]);
1192
- height = parseInt(match[1]);
1193
- if (width < 8 || width > 0x7fff) {
1194
- throw "HDR Bad header format, unsupported size";
1195
- }
1196
- lineIndex += line.length + 1;
1197
- return {
1198
- height: height,
1199
- width: width,
1200
- dataPosition: lineIndex,
1201
- };
1202
- }
1203
- /**
1204
- * Returns the cubemap information (each faces texture data) extracted from an RGBE texture.
1205
- * This RGBE texture needs to store the information as a panorama.
1206
- *
1207
- * More information on this format are available here:
1208
- * https://en.wikipedia.org/wiki/RGBE_image_format
1209
- *
1210
- * @param buffer The binary file stored in an array buffer.
1211
- * @param size The expected size of the extracted cubemap.
1212
- * @returns The Cube Map information.
1213
- */
1214
- static GetCubeMapTextureData(buffer, size, supersample = false) {
1215
- const uint8array = new Uint8Array(buffer);
1216
- const hdrInfo = this.RGBE_ReadHeader(uint8array);
1217
- const data = this.RGBE_ReadPixels(uint8array, hdrInfo);
1218
- const cubeMapData = PanoramaToCubeMapTools.ConvertPanoramaToCubemap(data, hdrInfo.width, hdrInfo.height, size, supersample);
1219
- return cubeMapData;
1220
- }
1221
- /**
1222
- * Returns the pixels data extracted from an RGBE texture.
1223
- * This pixels will be stored left to right up to down in the R G B order in one array.
1224
- *
1225
- * More information on this format are available here:
1226
- * https://en.wikipedia.org/wiki/RGBE_image_format
1227
- *
1228
- * @param uint8array The binary file stored in an array buffer.
1229
- * @param hdrInfo The header information of the file.
1230
- * @returns The pixels data in RGB right to left up to down order.
1231
- */
1232
- // eslint-disable-next-line @typescript-eslint/naming-convention
1233
- static RGBE_ReadPixels(uint8array, hdrInfo) {
1234
- return this._RGBEReadPixelsRLE(uint8array, hdrInfo);
1235
- }
1236
- static _RGBEReadPixelsRLE(uint8array, hdrInfo) {
1237
- let num_scanlines = hdrInfo.height;
1238
- const scanline_width = hdrInfo.width;
1239
- let a, b, c, d, count;
1240
- let dataIndex = hdrInfo.dataPosition;
1241
- let index = 0, endIndex = 0, i = 0;
1242
- const scanLineArrayBuffer = new ArrayBuffer(scanline_width * 4); // four channel R G B E
1243
- const scanLineArray = new Uint8Array(scanLineArrayBuffer);
1244
- // 3 channels of 4 bytes per pixel in float.
1245
- const resultBuffer = new ArrayBuffer(hdrInfo.width * hdrInfo.height * 4 * 3);
1246
- const resultArray = new Float32Array(resultBuffer);
1247
- // read in each successive scanline
1248
- while (num_scanlines > 0) {
1249
- a = uint8array[dataIndex++];
1250
- b = uint8array[dataIndex++];
1251
- c = uint8array[dataIndex++];
1252
- d = uint8array[dataIndex++];
1253
- if (a != 2 || b != 2 || c & 0x80 || hdrInfo.width < 8 || hdrInfo.width > 32767) {
1254
- return this._RGBEReadPixelsNOTRLE(uint8array, hdrInfo);
1255
- }
1256
- if (((c << 8) | d) != scanline_width) {
1257
- throw "HDR Bad header format, wrong scan line width";
1258
- }
1259
- index = 0;
1260
- // read each of the four channels for the scanline into the buffer
1261
- for (i = 0; i < 4; i++) {
1262
- endIndex = (i + 1) * scanline_width;
1263
- while (index < endIndex) {
1264
- a = uint8array[dataIndex++];
1265
- b = uint8array[dataIndex++];
1266
- if (a > 128) {
1267
- // a run of the same value
1268
- count = a - 128;
1269
- if (count == 0 || count > endIndex - index) {
1270
- throw "HDR Bad Format, bad scanline data (run)";
1271
- }
1272
- while (count-- > 0) {
1273
- scanLineArray[index++] = b;
1274
- }
1275
- }
1276
- else {
1277
- // a non-run
1278
- count = a;
1279
- if (count == 0 || count > endIndex - index) {
1280
- throw "HDR Bad Format, bad scanline data (non-run)";
1281
- }
1282
- scanLineArray[index++] = b;
1283
- if (--count > 0) {
1284
- for (let j = 0; j < count; j++) {
1285
- scanLineArray[index++] = uint8array[dataIndex++];
1286
- }
1287
- }
1288
- }
1289
- }
1290
- }
1291
- // now convert data from buffer into floats
1292
- for (i = 0; i < scanline_width; i++) {
1293
- a = scanLineArray[i];
1294
- b = scanLineArray[i + scanline_width];
1295
- c = scanLineArray[i + 2 * scanline_width];
1296
- d = scanLineArray[i + 3 * scanline_width];
1297
- this._Rgbe2float(resultArray, a, b, c, d, (hdrInfo.height - num_scanlines) * scanline_width * 3 + i * 3);
1298
- }
1299
- num_scanlines--;
1300
- }
1301
- return resultArray;
1302
- }
1303
- static _RGBEReadPixelsNOTRLE(uint8array, hdrInfo) {
1304
- // this file is not run length encoded
1305
- // read values sequentially
1306
- let num_scanlines = hdrInfo.height;
1307
- const scanline_width = hdrInfo.width;
1308
- let a, b, c, d, i;
1309
- let dataIndex = hdrInfo.dataPosition;
1310
- // 3 channels of 4 bytes per pixel in float.
1311
- const resultBuffer = new ArrayBuffer(hdrInfo.width * hdrInfo.height * 4 * 3);
1312
- const resultArray = new Float32Array(resultBuffer);
1313
- // read in each successive scanline
1314
- while (num_scanlines > 0) {
1315
- for (i = 0; i < hdrInfo.width; i++) {
1316
- a = uint8array[dataIndex++];
1317
- b = uint8array[dataIndex++];
1318
- c = uint8array[dataIndex++];
1319
- d = uint8array[dataIndex++];
1320
- this._Rgbe2float(resultArray, a, b, c, d, (hdrInfo.height - num_scanlines) * scanline_width * 3 + i * 3);
1321
- }
1322
- num_scanlines--;
1323
- }
1324
- return resultArray;
1325
- }
1326
- }
1327
-
1328
- // Do not edit.
1329
- const name$1 = "hdrFilteringVertexShader";
1330
- const shader$1 = `attribute vec2 position;
1331
- void main(void) {
1332
- mat3 view=mat3(up,right,front);
1333
- }`;
1334
- // Sideeffect
1335
- ShaderStore.ShadersStore[name$1] = shader$1;
1336
-
1337
- // Do not edit.
1338
- const name = "hdrFilteringPixelShader";
1339
- const shader = `#include<helperFunctions>
1340
- #include<importanceSampling>
1341
- #include<pbrBRDFFunctions>
1342
- #include<hdrFilteringFunctions>
1343
- uniform float alphaG;
1344
- // Sideeffect
1345
- ShaderStore.ShadersStore[name] = shader;
1346
-
1347
- /**
1348
- * Filters HDR maps to get correct renderings of PBR reflections
1349
- */
1350
- class HDRFiltering {
1351
- /**
1352
- * Instantiates HDR filter for reflection maps
1353
- *
1354
- * @param engine Thin engine
1355
- * @param options Options
1356
- */
1357
- constructor(engine, options = {}) {
1358
- this._lodGenerationOffset = 0;
1359
- this._lodGenerationScale = 0.8;
1360
- /**
1361
- * Quality switch for prefiltering. Should be set to `4096` unless
1362
- * you care about baking speed.
1363
- */
1364
- this.quality = 4096;
1365
- /**
1366
- * Scales pixel intensity for the input HDR map.
1367
- */
1368
- this.hdrScale = 1;
1369
- // pass
1370
- this._engine = engine;
1371
- this.hdrScale = options.hdrScale || this.hdrScale;
1372
- this.quality = options.quality || this.quality;
1373
- }
1374
- _createRenderTarget(size) {
1375
- let textureType = 0;
1376
- if (this._engine.getCaps().textureHalfFloatRender) {
1377
- textureType = 2;
1378
- }
1379
- else if (this._engine.getCaps().textureFloatRender) {
1380
- textureType = 1;
1381
- }
1382
- const rtWrapper = this._engine.createRenderTargetCubeTexture(size, {
1383
- format: 5,
1384
- type: textureType,
1385
- createMipMaps: true,
1386
- generateMipMaps: false,
1387
- generateDepthBuffer: false,
1388
- generateStencilBuffer: false,
1389
- samplingMode: 1,
1390
- });
1391
- this._engine.updateTextureWrappingMode(rtWrapper.texture, 0, 0, 0);
1392
- this._engine.updateTextureSamplingMode(3, rtWrapper.texture, true);
1393
- return rtWrapper;
1394
- }
1395
- _prefilterInternal(texture) {
1396
- const width = texture.getSize().width;
1397
- const mipmapsCount = Scalar.ILog2(width) + 1;
1398
- const effect = this._effectWrapper.effect;
1399
- const outputTexture = this._createRenderTarget(width);
1400
- this._effectRenderer.setViewport();
1401
- const intTexture = texture.getInternalTexture();
1402
- if (intTexture) {
1403
- // Just in case generate fresh clean mips.
1404
- this._engine.updateTextureSamplingMode(3, intTexture, true);
1405
- }
1406
- this._effectRenderer.applyEffectWrapper(this._effectWrapper);
1407
- const directions = [
1408
- [new Vector3(0, 0, -1), new Vector3(0, -1, 0), new Vector3(1, 0, 0)],
1409
- [new Vector3(0, 0, 1), new Vector3(0, -1, 0), new Vector3(-1, 0, 0)],
1410
- [new Vector3(1, 0, 0), new Vector3(0, 0, 1), new Vector3(0, 1, 0)],
1411
- [new Vector3(1, 0, 0), new Vector3(0, 0, -1), new Vector3(0, -1, 0)],
1412
- [new Vector3(1, 0, 0), new Vector3(0, -1, 0), new Vector3(0, 0, 1)],
1413
- [new Vector3(-1, 0, 0), new Vector3(0, -1, 0), new Vector3(0, 0, -1)], // NegativeZ
1414
- ];
1415
- effect.setFloat("hdrScale", this.hdrScale);
1416
- effect.setFloat2("vFilteringInfo", texture.getSize().width, mipmapsCount);
1417
- effect.setTexture("inputTexture", texture);
1418
- for (let face = 0; face < 6; face++) {
1419
- effect.setVector3("up", directions[face][0]);
1420
- effect.setVector3("right", directions[face][1]);
1421
- effect.setVector3("front", directions[face][2]);
1422
- for (let lod = 0; lod < mipmapsCount; lod++) {
1423
- this._engine.bindFramebuffer(outputTexture, face, undefined, undefined, true, lod);
1424
- this._effectRenderer.applyEffectWrapper(this._effectWrapper);
1425
- let alpha = Math.pow(2, (lod - this._lodGenerationOffset) / this._lodGenerationScale) / width;
1426
- if (lod === 0) {
1427
- alpha = 0;
1428
- }
1429
- effect.setFloat("alphaG", alpha);
1430
- this._effectRenderer.draw();
1431
- }
1432
- }
1433
- // Cleanup
1434
- this._effectRenderer.restoreStates();
1435
- this._engine.restoreDefaultFramebuffer();
1436
- this._engine._releaseTexture(texture._texture);
1437
- // Internal Swap
1438
- const type = outputTexture.texture.type;
1439
- const format = outputTexture.texture.format;
1440
- outputTexture._swapAndDie(texture._texture);
1441
- texture._texture.type = type;
1442
- texture._texture.format = format;
1443
- // New settings
1444
- texture.gammaSpace = false;
1445
- texture.lodGenerationOffset = this._lodGenerationOffset;
1446
- texture.lodGenerationScale = this._lodGenerationScale;
1447
- texture._prefiltered = true;
1448
- return texture;
1449
- }
1450
- _createEffect(texture, onCompiled) {
1451
- const defines = [];
1452
- if (texture.gammaSpace) {
1453
- defines.push("#define GAMMA_INPUT");
1454
- }
1455
- defines.push("#define NUM_SAMPLES " + this.quality + "u"); // unsigned int
1456
- const effectWrapper = new EffectWrapper({
1457
- engine: this._engine,
1458
- name: "hdrFiltering",
1459
- vertexShader: "hdrFiltering",
1460
- fragmentShader: "hdrFiltering",
1461
- samplerNames: ["inputTexture"],
1462
- uniformNames: ["vSampleDirections", "vWeights", "up", "right", "front", "vFilteringInfo", "hdrScale", "alphaG"],
1463
- useShaderStore: true,
1464
- defines,
1465
- onCompiled: onCompiled,
1466
- });
1467
- return effectWrapper;
1468
- }
1469
- /**
1470
- * Get a value indicating if the filter is ready to be used
1471
- * @param texture Texture to filter
1472
- * @returns true if the filter is ready
1473
- */
1474
- isReady(texture) {
1475
- return texture.isReady() && this._effectWrapper.effect.isReady();
1476
- }
1477
- /**
1478
- * Prefilters a cube texture to have mipmap levels representing roughness values.
1479
- * Prefiltering will be invoked at the end of next rendering pass.
1480
- * This has to be done once the map is loaded, and has not been prefiltered by a third party software.
1481
- * See http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf for more information
1482
- * @param texture Texture to filter
1483
- * @param onFinished Callback when filtering is done
1484
- * @returns Promise called when prefiltering is done
1485
- */
1486
- prefilter(texture, onFinished = null) {
1487
- if (!this._engine._features.allowTexturePrefiltering) {
1488
- Logger.Warn("HDR prefiltering is not available in WebGL 1., you can use real time filtering instead.");
1489
- return Promise.reject("HDR prefiltering is not available in WebGL 1., you can use real time filtering instead.");
1490
- }
1491
- return new Promise((resolve) => {
1492
- this._effectRenderer = new EffectRenderer(this._engine);
1493
- this._effectWrapper = this._createEffect(texture);
1494
- this._effectWrapper.effect.executeWhenCompiled(() => {
1495
- this._prefilterInternal(texture);
1496
- this._effectRenderer.dispose();
1497
- this._effectWrapper.dispose();
1498
- resolve();
1499
- if (onFinished) {
1500
- onFinished();
1501
- }
1502
- });
1503
- });
1504
- }
1505
- }
1506
-
1507
- /**
1508
- * This represents a texture coming from an HDR input.
1509
- *
1510
- * The only supported format is currently panorama picture stored in RGBE format.
1511
- * Example of such files can be found on Poly Haven: https://polyhaven.com/hdris
1512
- */
1513
- class HDRCubeTexture extends BaseTexture {
1514
- /**
1515
- * Sets whether or not the texture is blocking during loading.
1516
- */
1517
- set isBlocking(value) {
1518
- this._isBlocking = value;
1519
- }
1520
- /**
1521
- * Gets whether or not the texture is blocking during loading.
1522
- */
1523
- get isBlocking() {
1524
- return this._isBlocking;
1525
- }
1526
- /**
1527
- * Sets texture matrix rotation angle around Y axis in radians.
1528
- */
1529
- set rotationY(value) {
1530
- this._rotationY = value;
1531
- this.setReflectionTextureMatrix(Matrix.RotationY(this._rotationY));
1532
- }
1533
- /**
1534
- * Gets texture matrix rotation angle around Y axis radians.
1535
- */
1536
- get rotationY() {
1537
- return this._rotationY;
1538
- }
1539
- /**
1540
- * Gets or sets the size of the bounding box associated with the cube texture
1541
- * When defined, the cubemap will switch to local mode
1542
- * @see https://community.arm.com/graphics/b/blog/posts/reflections-based-on-local-cubemaps-in-unity
1543
- * @example https://www.babylonjs-playground.com/#RNASML
1544
- */
1545
- set boundingBoxSize(value) {
1546
- if (this._boundingBoxSize && this._boundingBoxSize.equals(value)) {
1547
- return;
1548
- }
1549
- this._boundingBoxSize = value;
1550
- const scene = this.getScene();
1551
- if (scene) {
1552
- scene.markAllMaterialsAsDirty(1);
1553
- }
1554
- }
1555
- get boundingBoxSize() {
1556
- return this._boundingBoxSize;
1557
- }
1558
- /**
1559
- * Instantiates an HDRTexture from the following parameters.
1560
- *
1561
- * @param url The location of the HDR raw data (Panorama stored in RGBE format)
1562
- * @param sceneOrEngine The scene or engine the texture will be used in
1563
- * @param size The cubemap desired size (the more it increases the longer the generation will be)
1564
- * @param noMipmap Forces to not generate the mipmap if true
1565
- * @param generateHarmonics Specifies whether you want to extract the polynomial harmonics during the generation process
1566
- * @param gammaSpace Specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space)
1567
- * @param prefilterOnLoad Prefilters HDR texture to allow use of this texture as a PBR reflection texture.
1568
- * @param onLoad
1569
- * @param onError
1570
- */
1571
- constructor(url, sceneOrEngine, size, noMipmap = false, generateHarmonics = true, gammaSpace = false, prefilterOnLoad = false, onLoad = null, onError = null, supersample = false) {
1572
- var _a;
1573
- super(sceneOrEngine);
1574
- this._generateHarmonics = true;
1575
- this._onError = null;
1576
- this._isBlocking = true;
1577
- this._rotationY = 0;
1578
- /**
1579
- * Gets or sets the center of the bounding box associated with the cube texture
1580
- * It must define where the camera used to render the texture was set
1581
- */
1582
- this.boundingBoxPosition = Vector3.Zero();
1583
- /**
1584
- * Observable triggered once the texture has been loaded.
1585
- */
1586
- this.onLoadObservable = new Observable();
1587
- if (!url) {
1588
- return;
1589
- }
1590
- this._coordinatesMode = Texture.CUBIC_MODE;
1591
- this.name = url;
1592
- this.url = url;
1593
- this.hasAlpha = false;
1594
- this.isCube = true;
1595
- this._textureMatrix = Matrix.Identity();
1596
- this._prefilterOnLoad = prefilterOnLoad;
1597
- this._onLoad = () => {
1598
- this.onLoadObservable.notifyObservers(this);
1599
- if (onLoad) {
1600
- onLoad();
1601
- }
1602
- };
1603
- this._onError = onError;
1604
- this.gammaSpace = gammaSpace;
1605
- this._noMipmap = noMipmap;
1606
- this._size = size;
1607
- this._supersample = supersample;
1608
- this._generateHarmonics = generateHarmonics;
1609
- this._texture = this._getFromCache(url, this._noMipmap, undefined, undefined, undefined, this.isCube);
1610
- if (!this._texture) {
1611
- if (!((_a = this.getScene()) === null || _a === void 0 ? void 0 : _a.useDelayedTextureLoading)) {
1612
- this._loadTexture();
1613
- }
1614
- else {
1615
- this.delayLoadState = 4;
1616
- }
1617
- }
1618
- else {
1619
- if (this._texture.isReady) {
1620
- Tools.SetImmediate(() => this._onLoad());
1621
- }
1622
- else {
1623
- this._texture.onLoadedObservable.add(this._onLoad);
1624
- }
1625
- }
1626
- }
1627
- /**
1628
- * Get the current class name of the texture useful for serialization or dynamic coding.
1629
- * @returns "HDRCubeTexture"
1630
- */
1631
- getClassName() {
1632
- return "HDRCubeTexture";
1633
- }
1634
- /**
1635
- * Occurs when the file is raw .hdr file.
1636
- */
1637
- _loadTexture() {
1638
- const engine = this._getEngine();
1639
- const caps = engine.getCaps();
1640
- let textureType = 0;
1641
- if (caps.textureFloat && caps.textureFloatLinearFiltering) {
1642
- textureType = 1;
1643
- }
1644
- else if (caps.textureHalfFloat && caps.textureHalfFloatLinearFiltering) {
1645
- textureType = 2;
1646
- }
1647
- const callback = (buffer) => {
1648
- this.lodGenerationOffset = 0.0;
1649
- this.lodGenerationScale = 0.8;
1650
- // Extract the raw linear data.
1651
- const data = HDRTools.GetCubeMapTextureData(buffer, this._size, this._supersample);
1652
- // Generate harmonics if needed.
1653
- if (this._generateHarmonics) {
1654
- const sphericalPolynomial = CubeMapToSphericalPolynomialTools.ConvertCubeMapToSphericalPolynomial(data);
1655
- this.sphericalPolynomial = sphericalPolynomial;
1656
- }
1657
- const results = [];
1658
- let byteArray = null;
1659
- let shortArray = null;
1660
- // Push each faces.
1661
- for (let j = 0; j < 6; j++) {
1662
- // Create fallback array
1663
- if (textureType === 2) {
1664
- shortArray = new Uint16Array(this._size * this._size * 3);
1665
- }
1666
- else if (textureType === 0) {
1667
- // 3 channels of 1 bytes per pixel in bytes.
1668
- byteArray = new Uint8Array(this._size * this._size * 3);
1669
- }
1670
- const dataFace = data[HDRCubeTexture._FacesMapping[j]];
1671
- // If special cases.
1672
- if (this.gammaSpace || shortArray || byteArray) {
1673
- for (let i = 0; i < this._size * this._size; i++) {
1674
- // Put in gamma space if requested.
1675
- if (this.gammaSpace) {
1676
- dataFace[i * 3 + 0] = Math.pow(dataFace[i * 3 + 0], ToGammaSpace);
1677
- dataFace[i * 3 + 1] = Math.pow(dataFace[i * 3 + 1], ToGammaSpace);
1678
- dataFace[i * 3 + 2] = Math.pow(dataFace[i * 3 + 2], ToGammaSpace);
1679
- }
1680
- // Convert to half float texture for fallback.
1681
- if (shortArray) {
1682
- shortArray[i * 3 + 0] = ToHalfFloat(dataFace[i * 3 + 0]);
1683
- shortArray[i * 3 + 1] = ToHalfFloat(dataFace[i * 3 + 1]);
1684
- shortArray[i * 3 + 2] = ToHalfFloat(dataFace[i * 3 + 2]);
1685
- }
1686
- // Convert to int texture for fallback.
1687
- if (byteArray) {
1688
- let r = Math.max(dataFace[i * 3 + 0] * 255, 0);
1689
- let g = Math.max(dataFace[i * 3 + 1] * 255, 0);
1690
- let b = Math.max(dataFace[i * 3 + 2] * 255, 0);
1691
- // May use luminance instead if the result is not accurate.
1692
- const max = Math.max(Math.max(r, g), b);
1693
- if (max > 255) {
1694
- const scale = 255 / max;
1695
- r *= scale;
1696
- g *= scale;
1697
- b *= scale;
1698
- }
1699
- byteArray[i * 3 + 0] = r;
1700
- byteArray[i * 3 + 1] = g;
1701
- byteArray[i * 3 + 2] = b;
1702
- }
1703
- }
1704
- }
1705
- if (shortArray) {
1706
- results.push(shortArray);
1707
- }
1708
- else if (byteArray) {
1709
- results.push(byteArray);
1710
- }
1711
- else {
1712
- results.push(dataFace);
1713
- }
1714
- }
1715
- return results;
1716
- };
1717
- if (engine._features.allowTexturePrefiltering && this._prefilterOnLoad) {
1718
- const previousOnLoad = this._onLoad;
1719
- const hdrFiltering = new HDRFiltering(engine);
1720
- this._onLoad = () => {
1721
- hdrFiltering.prefilter(this, previousOnLoad);
1722
- };
1723
- }
1724
- this._texture = engine.createRawCubeTextureFromUrl(this.url, this.getScene(), this._size, 4, textureType, this._noMipmap, callback, null, this._onLoad, this._onError);
1725
- }
1726
- clone() {
1727
- const newTexture = new HDRCubeTexture(this.url, this.getScene() || this._getEngine(), this._size, this._noMipmap, this._generateHarmonics, this.gammaSpace);
1728
- // Base texture
1729
- newTexture.level = this.level;
1730
- newTexture.wrapU = this.wrapU;
1731
- newTexture.wrapV = this.wrapV;
1732
- newTexture.coordinatesIndex = this.coordinatesIndex;
1733
- newTexture.coordinatesMode = this.coordinatesMode;
1734
- return newTexture;
1735
- }
1736
- // Methods
1737
- delayLoad() {
1738
- if (this.delayLoadState !== 4) {
1739
- return;
1740
- }
1741
- this.delayLoadState = 1;
1742
- this._texture = this._getFromCache(this.url, this._noMipmap);
1743
- if (!this._texture) {
1744
- this._loadTexture();
1745
- }
1746
- }
1747
- /**
1748
- * Get the texture reflection matrix used to rotate/transform the reflection.
1749
- * @returns the reflection matrix
1750
- */
1751
- getReflectionTextureMatrix() {
1752
- return this._textureMatrix;
1753
- }
1754
- /**
1755
- * Set the texture reflection matrix used to rotate/transform the reflection.
1756
- * @param value Define the reflection matrix to set
1757
- */
1758
- setReflectionTextureMatrix(value) {
1759
- var _a;
1760
- this._textureMatrix = value;
1761
- if (value.updateFlag === this._textureMatrix.updateFlag) {
1762
- return;
1763
- }
1764
- if (value.isIdentity() !== this._textureMatrix.isIdentity()) {
1765
- (_a = this.getScene()) === null || _a === void 0 ? void 0 : _a.markAllMaterialsAsDirty(1, (mat) => mat.getActiveTextures().indexOf(this) !== -1);
1766
- }
1767
- }
1768
- /**
1769
- * Dispose the texture and release its associated resources.
1770
- */
1771
- dispose() {
1772
- this.onLoadObservable.clear();
1773
- super.dispose();
1774
- }
1775
- /**
1776
- * Parses a JSON representation of an HDR Texture in order to create the texture
1777
- * @param parsedTexture Define the JSON representation
1778
- * @param scene Define the scene the texture should be created in
1779
- * @param rootUrl Define the root url in case we need to load relative dependencies
1780
- * @returns the newly created texture after parsing
1781
- */
1782
- static Parse(parsedTexture, scene, rootUrl) {
1783
- let texture = null;
1784
- if (parsedTexture.name && !parsedTexture.isRenderTarget) {
1785
- texture = new HDRCubeTexture(rootUrl + parsedTexture.name, scene, parsedTexture.size, parsedTexture.noMipmap, parsedTexture.generateHarmonics, parsedTexture.useInGammaSpace);
1786
- texture.name = parsedTexture.name;
1787
- texture.hasAlpha = parsedTexture.hasAlpha;
1788
- texture.level = parsedTexture.level;
1789
- texture.coordinatesMode = parsedTexture.coordinatesMode;
1790
- texture.isBlocking = parsedTexture.isBlocking;
1791
- }
1792
- if (texture) {
1793
- if (parsedTexture.boundingBoxPosition) {
1794
- texture.boundingBoxPosition = Vector3.FromArray(parsedTexture.boundingBoxPosition);
1795
- }
1796
- if (parsedTexture.boundingBoxSize) {
1797
- texture.boundingBoxSize = Vector3.FromArray(parsedTexture.boundingBoxSize);
1798
- }
1799
- if (parsedTexture.rotationY) {
1800
- texture.rotationY = parsedTexture.rotationY;
1801
- }
1802
- }
1803
- return texture;
1804
- }
1805
- serialize() {
1806
- if (!this.name) {
1807
- return null;
1808
- }
1809
- const serializationObject = {};
1810
- serializationObject.name = this.name;
1811
- serializationObject.hasAlpha = this.hasAlpha;
1812
- serializationObject.isCube = true;
1813
- serializationObject.level = this.level;
1814
- serializationObject.size = this._size;
1815
- serializationObject.coordinatesMode = this.coordinatesMode;
1816
- serializationObject.useInGammaSpace = this.gammaSpace;
1817
- serializationObject.generateHarmonics = this._generateHarmonics;
1818
- serializationObject.customType = "BABYLON.HDRCubeTexture";
1819
- serializationObject.noMipmap = this._noMipmap;
1820
- serializationObject.isBlocking = this._isBlocking;
1821
- serializationObject.rotationY = this._rotationY;
1822
- return serializationObject;
1823
- }
1824
- }
1825
- HDRCubeTexture._FacesMapping = ["right", "left", "up", "down", "front", "back"];
1826
- RegisterClass("BABYLON.HDRCubeTexture", HDRCubeTexture);
1827
-
1828
- /**
1829
- * This represents a texture coming from an equirectangular image supported by the web browser canvas.
1830
- */
1831
- class EquiRectangularCubeTexture extends BaseTexture {
1832
- /**
1833
- * Instantiates an EquiRectangularCubeTexture from the following parameters.
1834
- * @param url The location of the image
1835
- * @param scene The scene the texture will be used in
1836
- * @param size The cubemap desired size (the more it increases the longer the generation will be)
1837
- * @param noMipmap Forces to not generate the mipmap if true
1838
- * @param gammaSpace Specifies if the texture will be used in gamma or linear space
1839
- * (the PBR material requires those textures in linear space, but the standard material would require them in Gamma space)
1840
- * @param onLoad — defines a callback called when texture is loaded
1841
- * @param onError — defines a callback called if there is an error
1842
- */
1843
- constructor(url, scene, size, noMipmap = false, gammaSpace = true, onLoad = null, onError = null, supersample = false) {
1844
- super(scene);
1845
- this._onLoad = null;
1846
- this._onError = null;
1847
- if (!url) {
1848
- throw new Error("Image url is not set");
1849
- }
1850
- this._coordinatesMode = Texture.CUBIC_MODE;
1851
- this.name = url;
1852
- this.url = url;
1853
- this._size = size;
1854
- this._supersample = supersample;
1855
- this._noMipmap = noMipmap;
1856
- this.gammaSpace = gammaSpace;
1857
- this._onLoad = onLoad;
1858
- this._onError = onError;
1859
- this.hasAlpha = false;
1860
- this.isCube = true;
1861
- this._texture = this._getFromCache(url, this._noMipmap, undefined, undefined, undefined, this.isCube);
1862
- if (!this._texture) {
1863
- if (!scene.useDelayedTextureLoading) {
1864
- this._loadImage(this._loadTexture.bind(this), this._onError);
1865
- }
1866
- else {
1867
- this.delayLoadState = 4;
1868
- }
1869
- }
1870
- else if (onLoad) {
1871
- if (this._texture.isReady) {
1872
- Tools.SetImmediate(() => onLoad());
1873
- }
1874
- else {
1875
- this._texture.onLoadedObservable.add(onLoad);
1876
- }
1877
- }
1878
- }
1879
- /**
1880
- * Load the image data, by putting the image on a canvas and extracting its buffer.
1881
- * @param loadTextureCallback
1882
- * @param onError
1883
- */
1884
- _loadImage(loadTextureCallback, onError) {
1885
- const canvas = document.createElement("canvas");
1886
- LoadImage(this.url, (image) => {
1887
- this._width = image.width;
1888
- this._height = image.height;
1889
- canvas.width = this._width;
1890
- canvas.height = this._height;
1891
- const ctx = canvas.getContext("2d");
1892
- ctx.drawImage(image, 0, 0);
1893
- const imageData = ctx.getImageData(0, 0, image.width, image.height);
1894
- this._buffer = imageData.data.buffer;
1895
- canvas.remove();
1896
- loadTextureCallback();
1897
- }, (_, e) => {
1898
- if (onError) {
1899
- onError(`${this.getClassName()} could not be loaded`, e);
1900
- }
1901
- }, null);
1902
- }
1903
- /**
1904
- * Convert the image buffer into a cubemap and create a CubeTexture.
1905
- */
1906
- _loadTexture() {
1907
- const scene = this.getScene();
1908
- const callback = () => {
1909
- const imageData = this._getFloat32ArrayFromArrayBuffer(this._buffer);
1910
- // Extract the raw linear data.
1911
- const data = PanoramaToCubeMapTools.ConvertPanoramaToCubemap(imageData, this._width, this._height, this._size, this._supersample);
1912
- const results = [];
1913
- // Push each faces.
1914
- for (let i = 0; i < 6; i++) {
1915
- const dataFace = data[EquiRectangularCubeTexture._FacesMapping[i]];
1916
- results.push(dataFace);
1917
- }
1918
- return results;
1919
- };
1920
- if (!scene) {
1921
- return;
1922
- }
1923
- this._texture = scene
1924
- .getEngine()
1925
- .createRawCubeTextureFromUrl(this.url, scene, this._size, 4, scene.getEngine().getCaps().textureFloat ? 1 : 7, this._noMipmap, callback, null, this._onLoad, this._onError);
1926
- }
1927
- /**
1928
- * Convert the ArrayBuffer into a Float32Array and drop the transparency channel.
1929
- * @param buffer The ArrayBuffer that should be converted.
1930
- * @returns The buffer as Float32Array.
1931
- */
1932
- _getFloat32ArrayFromArrayBuffer(buffer) {
1933
- const dataView = new DataView(buffer);
1934
- const floatImageData = new Float32Array((buffer.byteLength * 3) / 4);
1935
- let k = 0;
1936
- for (let i = 0; i < buffer.byteLength; i++) {
1937
- // We drop the transparency channel, because we do not need/want it
1938
- if ((i + 1) % 4 !== 0) {
1939
- floatImageData[k++] = dataView.getUint8(i) / 255;
1940
- }
1941
- }
1942
- return floatImageData;
1943
- }
1944
- /**
1945
- * Get the current class name of the texture useful for serialization or dynamic coding.
1946
- * @returns "EquiRectangularCubeTexture"
1947
- */
1948
- getClassName() {
1949
- return "EquiRectangularCubeTexture";
1950
- }
1951
- /**
1952
- * Create a clone of the current EquiRectangularCubeTexture and return it.
1953
- * @returns A clone of the current EquiRectangularCubeTexture.
1954
- */
1955
- clone() {
1956
- const scene = this.getScene();
1957
- if (!scene) {
1958
- return this;
1959
- }
1960
- const newTexture = new EquiRectangularCubeTexture(this.url, scene, this._size, this._noMipmap, this.gammaSpace);
1961
- // Base texture
1962
- newTexture.level = this.level;
1963
- newTexture.wrapU = this.wrapU;
1964
- newTexture.wrapV = this.wrapV;
1965
- newTexture.coordinatesIndex = this.coordinatesIndex;
1966
- newTexture.coordinatesMode = this.coordinatesMode;
1967
- return newTexture;
1968
- }
1969
- }
1970
- /** The six faces of the cube. */
1971
- EquiRectangularCubeTexture._FacesMapping = ["right", "left", "up", "down", "front", "back"];
1972
-
1973
- /**
1974
- * Defines the list of states available for a task inside a AssetsManager
1975
- */
1976
- var AssetTaskState;
1977
- (function (AssetTaskState) {
1978
- /**
1979
- * Initialization
1980
- */
1981
- AssetTaskState[AssetTaskState["INIT"] = 0] = "INIT";
1982
- /**
1983
- * Running
1984
- */
1985
- AssetTaskState[AssetTaskState["RUNNING"] = 1] = "RUNNING";
1986
- /**
1987
- * Done
1988
- */
1989
- AssetTaskState[AssetTaskState["DONE"] = 2] = "DONE";
1990
- /**
1991
- * Error
1992
- */
1993
- AssetTaskState[AssetTaskState["ERROR"] = 3] = "ERROR";
1994
- })(AssetTaskState || (AssetTaskState = {}));
1995
- /**
1996
- * Define an abstract asset task used with a AssetsManager class to load assets into a scene
1997
- */
1998
- class AbstractAssetTask {
1999
- /**
2000
- * Creates a new AssetsManager
2001
- * @param name defines the name of the task
2002
- */
2003
- constructor(
2004
- /**
2005
- * Task name
2006
- */ name) {
2007
- this.name = name;
2008
- this._isCompleted = false;
2009
- this._taskState = AssetTaskState.INIT;
2010
- }
2011
- /**
2012
- * Get if the task is completed
2013
- */
2014
- get isCompleted() {
2015
- return this._isCompleted;
2016
- }
2017
- /**
2018
- * Gets the current state of the task
2019
- */
2020
- get taskState() {
2021
- return this._taskState;
2022
- }
2023
- /**
2024
- * Gets the current error object (if task is in error)
2025
- */
2026
- get errorObject() {
2027
- return this._errorObject;
2028
- }
2029
- /**
2030
- * Internal only
2031
- * @internal
2032
- */
2033
- _setErrorObject(message, exception) {
2034
- if (this._errorObject) {
2035
- return;
2036
- }
2037
- this._errorObject = {
2038
- message: message,
2039
- exception: exception,
2040
- };
2041
- }
2042
- /**
2043
- * Execute the current task
2044
- * @param scene defines the scene where you want your assets to be loaded
2045
- * @param onSuccess is a callback called when the task is successfully executed
2046
- * @param onError is a callback called if an error occurs
2047
- */
2048
- run(scene, onSuccess, onError) {
2049
- this._taskState = AssetTaskState.RUNNING;
2050
- this.runTask(scene, () => {
2051
- this._onDoneCallback(onSuccess, onError);
2052
- }, (msg, exception) => {
2053
- this._onErrorCallback(onError, msg, exception);
2054
- });
2055
- }
2056
- /**
2057
- * Execute the current task
2058
- * @param scene defines the scene where you want your assets to be loaded
2059
- * @param onSuccess is a callback called when the task is successfully executed
2060
- * @param onError is a callback called if an error occurs
2061
- */
2062
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2063
- runTask(scene, onSuccess, onError) {
2064
- throw new Error("runTask is not implemented");
2065
- }
2066
- /**
2067
- * Reset will set the task state back to INIT, so the next load call of the assets manager will execute this task again.
2068
- * This can be used with failed tasks that have the reason for failure fixed.
2069
- */
2070
- reset() {
2071
- this._taskState = AssetTaskState.INIT;
2072
- }
2073
- _onErrorCallback(onError, message, exception) {
2074
- this._taskState = AssetTaskState.ERROR;
2075
- this._errorObject = {
2076
- message: message,
2077
- exception: exception,
2078
- };
2079
- if (this.onError) {
2080
- this.onError(this, message, exception);
2081
- }
2082
- onError();
2083
- }
2084
- _onDoneCallback(onSuccess, onError) {
2085
- try {
2086
- this._taskState = AssetTaskState.DONE;
2087
- this._isCompleted = true;
2088
- if (this.onSuccess) {
2089
- this.onSuccess(this);
2090
- }
2091
- onSuccess();
2092
- }
2093
- catch (e) {
2094
- this._onErrorCallback(onError, "Task is done, error executing success callback(s)", e);
2095
- }
2096
- }
2097
- }
2098
- /**
2099
- * Class used to share progress information about assets loading
2100
- */
2101
- class AssetsProgressEvent {
2102
- /**
2103
- * Creates a AssetsProgressEvent
2104
- * @param remainingCount defines the number of remaining tasks to process
2105
- * @param totalCount defines the total number of tasks
2106
- * @param task defines the task that was just processed
2107
- */
2108
- constructor(remainingCount, totalCount, task) {
2109
- this.remainingCount = remainingCount;
2110
- this.totalCount = totalCount;
2111
- this.task = task;
2112
- }
2113
- }
2114
- /**
2115
- * Define a task used by AssetsManager to load assets into a container
2116
- */
2117
- class ContainerAssetTask extends AbstractAssetTask {
2118
- /**
2119
- * Creates a new ContainerAssetTask
2120
- * @param name defines the name of the task
2121
- * @param meshesNames defines the list of mesh's names you want to load
2122
- * @param rootUrl defines the root url to use as a base to load your meshes and associated resources
2123
- * @param sceneFilename defines the filename or File of the scene to load from
2124
- */
2125
- constructor(
2126
- /**
2127
- * Defines the name of the task
2128
- */
2129
- name,
2130
- /**
2131
- * Defines the list of mesh's names you want to load
2132
- */
2133
- meshesNames,
2134
- /**
2135
- * Defines the root url to use as a base to load your meshes and associated resources
2136
- */
2137
- rootUrl,
2138
- /**
2139
- * Defines the filename or File of the scene to load from
2140
- */
2141
- sceneFilename,
2142
- /**
2143
- * Defines the extension to use to load the scene (if not defined, ".babylon" will be used)
2144
- */
2145
- extension) {
2146
- super(name);
2147
- this.name = name;
2148
- this.meshesNames = meshesNames;
2149
- this.rootUrl = rootUrl;
2150
- this.sceneFilename = sceneFilename;
2151
- this.extension = extension;
2152
- }
2153
- /**
2154
- * Execute the current task
2155
- * @param scene defines the scene where you want your assets to be loaded
2156
- * @param onSuccess is a callback called when the task is successfully executed
2157
- * @param onError is a callback called if an error occurs
2158
- */
2159
- runTask(scene, onSuccess, onError) {
2160
- SceneLoader.LoadAssetContainer(this.rootUrl, this.sceneFilename, scene, (container) => {
2161
- this.loadedContainer = container;
2162
- this.loadedMeshes = container.meshes;
2163
- this.loadedTransformNodes = container.transformNodes;
2164
- this.loadedParticleSystems = container.particleSystems;
2165
- this.loadedSkeletons = container.skeletons;
2166
- this.loadedAnimationGroups = container.animationGroups;
2167
- onSuccess();
2168
- }, null, (scene, message, exception) => {
2169
- onError(message, exception);
2170
- }, this.extension);
2171
- }
2172
- }
2173
- /**
2174
- * Define a task used by AssetsManager to load meshes
2175
- */
2176
- class MeshAssetTask extends AbstractAssetTask {
2177
- /**
2178
- * Creates a new MeshAssetTask
2179
- * @param name defines the name of the task
2180
- * @param meshesNames defines the list of mesh's names you want to load
2181
- * @param rootUrl defines the root url to use as a base to load your meshes and associated resources
2182
- * @param sceneFilename defines the filename or File of the scene to load from
2183
- */
2184
- constructor(
2185
- /**
2186
- * Defines the name of the task
2187
- */
2188
- name,
2189
- /**
2190
- * Defines the list of mesh's names you want to load
2191
- */
2192
- meshesNames,
2193
- /**
2194
- * Defines the root url to use as a base to load your meshes and associated resources
2195
- */
2196
- rootUrl,
2197
- /**
2198
- * Defines the filename or File of the scene to load from
2199
- */
2200
- sceneFilename,
2201
- /**
2202
- * Defines the extension to use to load the scene (if not defined, ".babylon" will be used)
2203
- */
2204
- extension) {
2205
- super(name);
2206
- this.name = name;
2207
- this.meshesNames = meshesNames;
2208
- this.rootUrl = rootUrl;
2209
- this.sceneFilename = sceneFilename;
2210
- this.extension = extension;
2211
- }
2212
- /**
2213
- * Execute the current task
2214
- * @param scene defines the scene where you want your assets to be loaded
2215
- * @param onSuccess is a callback called when the task is successfully executed
2216
- * @param onError is a callback called if an error occurs
2217
- */
2218
- runTask(scene, onSuccess, onError) {
2219
- SceneLoader.ImportMesh(this.meshesNames, this.rootUrl, this.sceneFilename, scene, (meshes, particleSystems, skeletons, animationGroups, transformNodes) => {
2220
- this.loadedMeshes = meshes;
2221
- this.loadedTransformNodes = transformNodes;
2222
- this.loadedParticleSystems = particleSystems;
2223
- this.loadedSkeletons = skeletons;
2224
- this.loadedAnimationGroups = animationGroups;
2225
- onSuccess();
2226
- }, null, (scene, message, exception) => {
2227
- onError(message, exception);
2228
- }, this.extension);
2229
- }
2230
- }
2231
- /**
2232
- * Define a task used by AssetsManager to load text content
2233
- */
2234
- class TextFileAssetTask extends AbstractAssetTask {
2235
- /**
2236
- * Creates a new TextFileAssetTask object
2237
- * @param name defines the name of the task
2238
- * @param url defines the location of the file to load
2239
- */
2240
- constructor(
2241
- /**
2242
- * Defines the name of the task
2243
- */
2244
- name,
2245
- /**
2246
- * Defines the location of the file to load
2247
- */
2248
- url) {
2249
- super(name);
2250
- this.name = name;
2251
- this.url = url;
2252
- }
2253
- /**
2254
- * Execute the current task
2255
- * @param scene defines the scene where you want your assets to be loaded
2256
- * @param onSuccess is a callback called when the task is successfully executed
2257
- * @param onError is a callback called if an error occurs
2258
- */
2259
- runTask(scene, onSuccess, onError) {
2260
- scene._loadFile(this.url, (data) => {
2261
- this.text = data;
2262
- onSuccess();
2263
- }, undefined, false, false, (request, exception) => {
2264
- if (request) {
2265
- onError(request.status + " " + request.statusText, exception);
2266
- }
2267
- });
2268
- }
2269
- }
2270
- /**
2271
- * Define a task used by AssetsManager to load binary data
2272
- */
2273
- class BinaryFileAssetTask extends AbstractAssetTask {
2274
- /**
2275
- * Creates a new BinaryFileAssetTask object
2276
- * @param name defines the name of the new task
2277
- * @param url defines the location of the file to load
2278
- */
2279
- constructor(
2280
- /**
2281
- * Defines the name of the task
2282
- */
2283
- name,
2284
- /**
2285
- * Defines the location of the file to load
2286
- */
2287
- url) {
2288
- super(name);
2289
- this.name = name;
2290
- this.url = url;
2291
- }
2292
- /**
2293
- * Execute the current task
2294
- * @param scene defines the scene where you want your assets to be loaded
2295
- * @param onSuccess is a callback called when the task is successfully executed
2296
- * @param onError is a callback called if an error occurs
2297
- */
2298
- runTask(scene, onSuccess, onError) {
2299
- scene._loadFile(this.url, (data) => {
2300
- this.data = data;
2301
- onSuccess();
2302
- }, undefined, true, true, (request, exception) => {
2303
- if (request) {
2304
- onError(request.status + " " + request.statusText, exception);
2305
- }
2306
- });
2307
- }
2308
- }
2309
- /**
2310
- * Define a task used by AssetsManager to load images
2311
- */
2312
- class ImageAssetTask extends AbstractAssetTask {
2313
- /**
2314
- * Creates a new ImageAssetTask
2315
- * @param name defines the name of the task
2316
- * @param url defines the location of the image to load
2317
- */
2318
- constructor(
2319
- /**
2320
- * Defines the name of the task
2321
- */
2322
- name,
2323
- /**
2324
- * Defines the location of the image to load
2325
- */
2326
- url) {
2327
- super(name);
2328
- this.name = name;
2329
- this.url = url;
2330
- }
2331
- /**
2332
- * Execute the current task
2333
- * @param scene defines the scene where you want your assets to be loaded
2334
- * @param onSuccess is a callback called when the task is successfully executed
2335
- * @param onError is a callback called if an error occurs
2336
- */
2337
- runTask(scene, onSuccess, onError) {
2338
- const img = new Image();
2339
- Tools.SetCorsBehavior(this.url, img);
2340
- img.onload = () => {
2341
- this.image = img;
2342
- onSuccess();
2343
- };
2344
- img.onerror = (err) => {
2345
- onError("Error loading image", err);
2346
- };
2347
- img.src = this.url;
2348
- }
2349
- }
2350
- /**
2351
- * Define a task used by AssetsManager to load 2D textures
2352
- */
2353
- class TextureAssetTask extends AbstractAssetTask {
2354
- /**
2355
- * Creates a new TextureAssetTask object
2356
- * @param name defines the name of the task
2357
- * @param url defines the location of the file to load
2358
- * @param noMipmap defines if mipmap should not be generated (default is false)
2359
- * @param invertY defines if texture must be inverted on Y axis (default is true)
2360
- * @param samplingMode defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
2361
- */
2362
- constructor(
2363
- /**
2364
- * Defines the name of the task
2365
- */
2366
- name,
2367
- /**
2368
- * Defines the location of the file to load
2369
- */
2370
- url,
2371
- /**
2372
- * Defines if mipmap should not be generated (default is false)
2373
- */
2374
- noMipmap,
2375
- /**
2376
- * Defines if texture must be inverted on Y axis (default is true)
2377
- */
2378
- invertY = true,
2379
- /**
2380
- * Defines the sampling mode to use (default is Texture.TRILINEAR_SAMPLINGMODE)
2381
- */
2382
- samplingMode = Texture.TRILINEAR_SAMPLINGMODE) {
2383
- super(name);
2384
- this.name = name;
2385
- this.url = url;
2386
- this.noMipmap = noMipmap;
2387
- this.invertY = invertY;
2388
- this.samplingMode = samplingMode;
2389
- }
2390
- /**
2391
- * Execute the current task
2392
- * @param scene defines the scene where you want your assets to be loaded
2393
- * @param onSuccess is a callback called when the task is successfully executed
2394
- * @param onError is a callback called if an error occurs
2395
- */
2396
- runTask(scene, onSuccess, onError) {
2397
- const onload = () => {
2398
- onSuccess();
2399
- };
2400
- const onerror = (message, exception) => {
2401
- onError(message, exception);
2402
- };
2403
- this.texture = new Texture(this.url, scene, this.noMipmap, this.invertY, this.samplingMode, onload, onerror);
2404
- }
2405
- }
2406
- /**
2407
- * Define a task used by AssetsManager to load cube textures
2408
- */
2409
- class CubeTextureAssetTask extends AbstractAssetTask {
2410
- /**
2411
- * Creates a new CubeTextureAssetTask
2412
- * @param name defines the name of the task
2413
- * @param url defines the location of the files to load (You have to specify the folder where the files are + filename with no extension)
2414
- * @param extensions defines the extensions to use to load files (["_px", "_py", "_pz", "_nx", "_ny", "_nz"] by default)
2415
- * @param noMipmap defines if mipmaps should not be generated (default is false)
2416
- * @param files defines the explicit list of files (undefined by default)
2417
- * @param prefiltered
2418
- */
2419
- constructor(
2420
- /**
2421
- * Defines the name of the task
2422
- */
2423
- name,
2424
- /**
2425
- * Defines the location of the files to load (You have to specify the folder where the files are + filename with no extension)
2426
- */
2427
- url,
2428
- /**
2429
- * Defines the extensions to use to load files (["_px", "_py", "_pz", "_nx", "_ny", "_nz"] by default)
2430
- */
2431
- extensions,
2432
- /**
2433
- * Defines if mipmaps should not be generated (default is false)
2434
- */
2435
- noMipmap,
2436
- /**
2437
- * Defines the explicit list of files (undefined by default)
2438
- */
2439
- files,
2440
- /**
2441
- * Defines the prefiltered texture option (default is false)
2442
- */
2443
- prefiltered) {
2444
- super(name);
2445
- this.name = name;
2446
- this.url = url;
2447
- this.extensions = extensions;
2448
- this.noMipmap = noMipmap;
2449
- this.files = files;
2450
- this.prefiltered = prefiltered;
2451
- }
2452
- /**
2453
- * Execute the current task
2454
- * @param scene defines the scene where you want your assets to be loaded
2455
- * @param onSuccess is a callback called when the task is successfully executed
2456
- * @param onError is a callback called if an error occurs
2457
- */
2458
- runTask(scene, onSuccess, onError) {
2459
- const onload = () => {
2460
- onSuccess();
2461
- };
2462
- const onerror = (message, exception) => {
2463
- onError(message, exception);
2464
- };
2465
- this.texture = new CubeTexture(this.url, scene, this.extensions, this.noMipmap, this.files, onload, onerror, undefined, this.prefiltered);
2466
- }
2467
- }
2468
- /**
2469
- * Define a task used by AssetsManager to load HDR cube textures
2470
- */
2471
- class HDRCubeTextureAssetTask extends AbstractAssetTask {
2472
- /**
2473
- * Creates a new HDRCubeTextureAssetTask object
2474
- * @param name defines the name of the task
2475
- * @param url defines the location of the file to load
2476
- * @param size defines the desired size (the more it increases the longer the generation will be) If the size is omitted this implies you are using a preprocessed cubemap.
2477
- * @param noMipmap defines if mipmaps should not be generated (default is false)
2478
- * @param generateHarmonics specifies whether you want to extract the polynomial harmonics during the generation process (default is true)
2479
- * @param gammaSpace specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space) (default is false)
2480
- * @param reserved Internal use only
2481
- */
2482
- constructor(
2483
- /**
2484
- * Defines the name of the task
2485
- */
2486
- name,
2487
- /**
2488
- * Defines the location of the file to load
2489
- */
2490
- url,
2491
- /**
2492
- * Defines the desired size (the more it increases the longer the generation will be)
2493
- */
2494
- size,
2495
- /**
2496
- * Defines if mipmaps should not be generated (default is false)
2497
- */
2498
- noMipmap = false,
2499
- /**
2500
- * Specifies whether you want to extract the polynomial harmonics during the generation process (default is true)
2501
- */
2502
- generateHarmonics = true,
2503
- /**
2504
- * Specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space) (default is false)
2505
- */
2506
- gammaSpace = false,
2507
- /**
2508
- * Internal Use Only
2509
- */
2510
- reserved = false) {
2511
- super(name);
2512
- this.name = name;
2513
- this.url = url;
2514
- this.size = size;
2515
- this.noMipmap = noMipmap;
2516
- this.generateHarmonics = generateHarmonics;
2517
- this.gammaSpace = gammaSpace;
2518
- this.reserved = reserved;
2519
- }
2520
- /**
2521
- * Execute the current task
2522
- * @param scene defines the scene where you want your assets to be loaded
2523
- * @param onSuccess is a callback called when the task is successfully executed
2524
- * @param onError is a callback called if an error occurs
2525
- */
2526
- runTask(scene, onSuccess, onError) {
2527
- const onload = () => {
2528
- onSuccess();
2529
- };
2530
- const onerror = (message, exception) => {
2531
- onError(message, exception);
2532
- };
2533
- this.texture = new HDRCubeTexture(this.url, scene, this.size, this.noMipmap, this.generateHarmonics, this.gammaSpace, this.reserved, onload, onerror);
2534
- }
2535
- }
2536
- /**
2537
- * Define a task used by AssetsManager to load Equirectangular cube textures
2538
- */
2539
- class EquiRectangularCubeTextureAssetTask extends AbstractAssetTask {
2540
- /**
2541
- * Creates a new EquiRectangularCubeTextureAssetTask object
2542
- * @param name defines the name of the task
2543
- * @param url defines the location of the file to load
2544
- * @param size defines the desired size (the more it increases the longer the generation will be)
2545
- * If the size is omitted this implies you are using a preprocessed cubemap.
2546
- * @param noMipmap defines if mipmaps should not be generated (default is false)
2547
- * @param gammaSpace specifies if the texture will be used in gamma or linear space
2548
- * (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space)
2549
- * (default is true)
2550
- */
2551
- constructor(
2552
- /**
2553
- * Defines the name of the task
2554
- */
2555
- name,
2556
- /**
2557
- * Defines the location of the file to load
2558
- */
2559
- url,
2560
- /**
2561
- * Defines the desired size (the more it increases the longer the generation will be)
2562
- */
2563
- size,
2564
- /**
2565
- * Defines if mipmaps should not be generated (default is false)
2566
- */
2567
- noMipmap = false,
2568
- /**
2569
- * Specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space,
2570
- * but the standard material would require them in Gamma space) (default is true)
2571
- */
2572
- gammaSpace = true) {
2573
- super(name);
2574
- this.name = name;
2575
- this.url = url;
2576
- this.size = size;
2577
- this.noMipmap = noMipmap;
2578
- this.gammaSpace = gammaSpace;
2579
- }
2580
- /**
2581
- * Execute the current task
2582
- * @param scene defines the scene where you want your assets to be loaded
2583
- * @param onSuccess is a callback called when the task is successfully executed
2584
- * @param onError is a callback called if an error occurs
2585
- */
2586
- runTask(scene, onSuccess, onError) {
2587
- const onload = () => {
2588
- onSuccess();
2589
- };
2590
- const onerror = (message, exception) => {
2591
- onError(message, exception);
2592
- };
2593
- this.texture = new EquiRectangularCubeTexture(this.url, scene, this.size, this.noMipmap, this.gammaSpace, onload, onerror);
2594
- }
2595
- }
2596
- /**
2597
- * This class can be used to easily import assets into a scene
2598
- * @see https://doc.babylonjs.com/features/featuresDeepDive/importers/assetManager
2599
- */
2600
- class AssetsManager {
2601
- /**
2602
- * Creates a new AssetsManager
2603
- * @param scene defines the scene to work on
2604
- */
2605
- constructor(scene) {
2606
- this._isLoading = false;
2607
- this._tasks = new Array();
2608
- this._waitingTasksCount = 0;
2609
- this._totalTasksCount = 0;
2610
- /**
2611
- * Observable called when all tasks are processed
2612
- */
2613
- this.onTaskSuccessObservable = new Observable();
2614
- /**
2615
- * Observable called when a task had an error
2616
- */
2617
- this.onTaskErrorObservable = new Observable();
2618
- /**
2619
- * Observable called when all tasks were executed
2620
- */
2621
- this.onTasksDoneObservable = new Observable();
2622
- /**
2623
- * Observable called when a task is done (whatever the result is)
2624
- */
2625
- this.onProgressObservable = new Observable();
2626
- /**
2627
- * Gets or sets a boolean defining if the AssetsManager should use the default loading screen
2628
- * @see https://doc.babylonjs.com/features/featuresDeepDive/scene/customLoadingScreen
2629
- */
2630
- this.useDefaultLoadingScreen = true;
2631
- /**
2632
- * Gets or sets a boolean defining if the AssetsManager should automatically hide the loading screen
2633
- * when all assets have been downloaded.
2634
- * If set to false, you need to manually call in hideLoadingUI() once your scene is ready.
2635
- */
2636
- this.autoHideLoadingUI = true;
2637
- this._scene = scene || EngineStore.LastCreatedScene;
2638
- }
2639
- /**
2640
- * Add a ContainerAssetTask to the list of active tasks
2641
- * @param taskName defines the name of the new task
2642
- * @param meshesNames defines the name of meshes to load
2643
- * @param rootUrl defines the root url to use to locate files
2644
- * @param sceneFilename defines the filename of the scene file or the File itself
2645
- * @param extension defines the extension to use to load the file
2646
- * @returns a new ContainerAssetTask object
2647
- */
2648
- addContainerTask(taskName, meshesNames, rootUrl, sceneFilename, extension) {
2649
- const task = new ContainerAssetTask(taskName, meshesNames, rootUrl, sceneFilename, extension);
2650
- this._tasks.push(task);
2651
- return task;
2652
- }
2653
- /**
2654
- * Add a MeshAssetTask to the list of active tasks
2655
- * @param taskName defines the name of the new task
2656
- * @param meshesNames defines the name of meshes to load
2657
- * @param rootUrl defines the root url to use to locate files
2658
- * @param sceneFilename defines the filename of the scene file or the File itself
2659
- * @param extension defines the extension to use to load the file
2660
- * @returns a new MeshAssetTask object
2661
- */
2662
- addMeshTask(taskName, meshesNames, rootUrl, sceneFilename, extension) {
2663
- const task = new MeshAssetTask(taskName, meshesNames, rootUrl, sceneFilename, extension);
2664
- this._tasks.push(task);
2665
- return task;
2666
- }
2667
- /**
2668
- * Add a TextFileAssetTask to the list of active tasks
2669
- * @param taskName defines the name of the new task
2670
- * @param url defines the url of the file to load
2671
- * @returns a new TextFileAssetTask object
2672
- */
2673
- addTextFileTask(taskName, url) {
2674
- const task = new TextFileAssetTask(taskName, url);
2675
- this._tasks.push(task);
2676
- return task;
2677
- }
2678
- /**
2679
- * Add a BinaryFileAssetTask to the list of active tasks
2680
- * @param taskName defines the name of the new task
2681
- * @param url defines the url of the file to load
2682
- * @returns a new BinaryFileAssetTask object
2683
- */
2684
- addBinaryFileTask(taskName, url) {
2685
- const task = new BinaryFileAssetTask(taskName, url);
2686
- this._tasks.push(task);
2687
- return task;
2688
- }
2689
- /**
2690
- * Add a ImageAssetTask to the list of active tasks
2691
- * @param taskName defines the name of the new task
2692
- * @param url defines the url of the file to load
2693
- * @returns a new ImageAssetTask object
2694
- */
2695
- addImageTask(taskName, url) {
2696
- const task = new ImageAssetTask(taskName, url);
2697
- this._tasks.push(task);
2698
- return task;
2699
- }
2700
- /**
2701
- * Add a TextureAssetTask to the list of active tasks
2702
- * @param taskName defines the name of the new task
2703
- * @param url defines the url of the file to load
2704
- * @param noMipmap defines if the texture must not receive mipmaps (false by default)
2705
- * @param invertY defines if you want to invert Y axis of the loaded texture (true by default)
2706
- * @param samplingMode defines the sampling mode to use (Texture.TRILINEAR_SAMPLINGMODE by default)
2707
- * @returns a new TextureAssetTask object
2708
- */
2709
- addTextureTask(taskName, url, noMipmap, invertY, samplingMode = Texture.TRILINEAR_SAMPLINGMODE) {
2710
- const task = new TextureAssetTask(taskName, url, noMipmap, invertY, samplingMode);
2711
- this._tasks.push(task);
2712
- return task;
2713
- }
2714
- /**
2715
- * Add a CubeTextureAssetTask to the list of active tasks
2716
- * @param taskName defines the name of the new task
2717
- * @param url defines the url of the file to load
2718
- * @param extensions defines the extension to use to load the cube map (can be null)
2719
- * @param noMipmap defines if the texture must not receive mipmaps (false by default)
2720
- * @param files defines the list of files to load (can be null)
2721
- * @param prefiltered defines the prefiltered texture option (default is false)
2722
- * @returns a new CubeTextureAssetTask object
2723
- */
2724
- addCubeTextureTask(taskName, url, extensions, noMipmap, files, prefiltered) {
2725
- const task = new CubeTextureAssetTask(taskName, url, extensions, noMipmap, files, prefiltered);
2726
- this._tasks.push(task);
2727
- return task;
2728
- }
2729
- /**
2730
- *
2731
- * Add a HDRCubeTextureAssetTask to the list of active tasks
2732
- * @param taskName defines the name of the new task
2733
- * @param url defines the url of the file to load
2734
- * @param size defines the size you want for the cubemap (can be null)
2735
- * @param noMipmap defines if the texture must not receive mipmaps (false by default)
2736
- * @param generateHarmonics defines if you want to automatically generate (true by default)
2737
- * @param gammaSpace specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space) (default is false)
2738
- * @param reserved Internal use only
2739
- * @returns a new HDRCubeTextureAssetTask object
2740
- */
2741
- addHDRCubeTextureTask(taskName, url, size, noMipmap = false, generateHarmonics = true, gammaSpace = false, reserved = false) {
2742
- const task = new HDRCubeTextureAssetTask(taskName, url, size, noMipmap, generateHarmonics, gammaSpace, reserved);
2743
- this._tasks.push(task);
2744
- return task;
2745
- }
2746
- /**
2747
- *
2748
- * Add a EquiRectangularCubeTextureAssetTask to the list of active tasks
2749
- * @param taskName defines the name of the new task
2750
- * @param url defines the url of the file to load
2751
- * @param size defines the size you want for the cubemap (can be null)
2752
- * @param noMipmap defines if the texture must not receive mipmaps (false by default)
2753
- * @param gammaSpace Specifies if the texture will be used in gamma or linear space
2754
- * (the PBR material requires those textures in linear space, but the standard material would require them in Gamma space)
2755
- * @returns a new EquiRectangularCubeTextureAssetTask object
2756
- */
2757
- addEquiRectangularCubeTextureAssetTask(taskName, url, size, noMipmap = false, gammaSpace = true) {
2758
- const task = new EquiRectangularCubeTextureAssetTask(taskName, url, size, noMipmap, gammaSpace);
2759
- this._tasks.push(task);
2760
- return task;
2761
- }
2762
- /**
2763
- * Remove a task from the assets manager.
2764
- * @param task the task to remove
2765
- */
2766
- removeTask(task) {
2767
- const index = this._tasks.indexOf(task);
2768
- if (index > -1) {
2769
- this._tasks.splice(index, 1);
2770
- }
2771
- }
2772
- _decreaseWaitingTasksCount(task) {
2773
- this._waitingTasksCount--;
2774
- try {
2775
- if (this.onProgress) {
2776
- this.onProgress(this._waitingTasksCount, this._totalTasksCount, task);
2777
- }
2778
- this.onProgressObservable.notifyObservers(new AssetsProgressEvent(this._waitingTasksCount, this._totalTasksCount, task));
2779
- }
2780
- catch (e) {
2781
- Logger.Error("Error running progress callbacks.");
2782
- console.log(e);
2783
- }
2784
- if (this._waitingTasksCount === 0) {
2785
- try {
2786
- const currentTasks = this._tasks.slice();
2787
- if (this.onFinish) {
2788
- // Calling onFinish with immutable array of tasks
2789
- this.onFinish(currentTasks);
2790
- }
2791
- // Let's remove successful tasks
2792
- for (const task of currentTasks) {
2793
- if (task.taskState === AssetTaskState.DONE) {
2794
- const index = this._tasks.indexOf(task);
2795
- if (index > -1) {
2796
- this._tasks.splice(index, 1);
2797
- }
2798
- }
2799
- }
2800
- this.onTasksDoneObservable.notifyObservers(this._tasks);
2801
- }
2802
- catch (e) {
2803
- Logger.Error("Error running tasks-done callbacks.");
2804
- console.log(e);
2805
- }
2806
- this._isLoading = false;
2807
- if (this.autoHideLoadingUI) {
2808
- this._scene.getEngine().hideLoadingUI();
2809
- }
2810
- }
2811
- }
2812
- _runTask(task) {
2813
- const done = () => {
2814
- try {
2815
- if (this.onTaskSuccess) {
2816
- this.onTaskSuccess(task);
2817
- }
2818
- this.onTaskSuccessObservable.notifyObservers(task);
2819
- this._decreaseWaitingTasksCount(task);
2820
- }
2821
- catch (e) {
2822
- error("Error executing task success callbacks", e);
2823
- }
2824
- };
2825
- const error = (message, exception) => {
2826
- task._setErrorObject(message, exception);
2827
- if (this.onTaskError) {
2828
- this.onTaskError(task);
2829
- }
2830
- else if (!task.onError) {
2831
- Logger.Error(this._formatTaskErrorMessage(task));
2832
- }
2833
- this.onTaskErrorObservable.notifyObservers(task);
2834
- this._decreaseWaitingTasksCount(task);
2835
- };
2836
- task.run(this._scene, done, error);
2837
- }
2838
- _formatTaskErrorMessage(task) {
2839
- let errorMessage = "Unable to complete task " + task.name;
2840
- if (task.errorObject.message) {
2841
- errorMessage += `: ${task.errorObject.message}`;
2842
- }
2843
- if (task.errorObject.exception) {
2844
- errorMessage += `: ${task.errorObject.exception}`;
2845
- }
2846
- return errorMessage;
2847
- }
2848
- /**
2849
- * Reset the AssetsManager and remove all tasks
2850
- * @returns the current instance of the AssetsManager
2851
- */
2852
- reset() {
2853
- this._isLoading = false;
2854
- this._tasks = new Array();
2855
- return this;
2856
- }
2857
- /**
2858
- * Start the loading process
2859
- * @returns the current instance of the AssetsManager
2860
- */
2861
- load() {
2862
- if (this._isLoading) {
2863
- return this;
2864
- }
2865
- this._isLoading = true;
2866
- this._waitingTasksCount = this._tasks.length;
2867
- this._totalTasksCount = this._tasks.length;
2868
- if (this._waitingTasksCount === 0) {
2869
- this._isLoading = false;
2870
- if (this.onFinish) {
2871
- this.onFinish(this._tasks);
2872
- }
2873
- this.onTasksDoneObservable.notifyObservers(this._tasks);
2874
- return this;
2875
- }
2876
- if (this.useDefaultLoadingScreen) {
2877
- this._scene.getEngine().displayLoadingUI();
2878
- }
2879
- for (let index = 0; index < this._tasks.length; index++) {
2880
- const task = this._tasks[index];
2881
- if (task.taskState === AssetTaskState.INIT) {
2882
- this._runTask(task);
2883
- }
2884
- }
2885
- return this;
2886
- }
2887
- /**
2888
- * Start the loading process as an async operation
2889
- * @returns a promise returning the list of failed tasks
2890
- */
2891
- loadAsync() {
2892
- return new Promise((resolve, reject) => {
2893
- if (this._isLoading) {
2894
- resolve();
2895
- return;
2896
- }
2897
- this.onTasksDoneObservable.addOnce((remainingTasks) => {
2898
- if (remainingTasks && remainingTasks.length) {
2899
- reject(remainingTasks);
2900
- }
2901
- else {
2902
- resolve();
2903
- }
2904
- });
2905
- this.load();
2906
- });
2907
- }
2908
- }
2909
-
2910
- /**
2911
- * Management object used to manage model and material variants
2912
- * for a specific instance of the 3D preview. This class should exist for
2913
- * the lifetime of any preview to track state relating to variant changes.
2914
- */
2915
- class VariantManager {
2916
- constructor(scene, renameClonedAsset, setBaseModelEnabled) {
2917
- /**
2918
- * Store encountered materials
2919
- */
2920
- this.materialVariantMap = new Map();
2921
- /**
2922
- * A list of model variant applications that replaced the base model,
2923
- * we store these internally to avoid having to lookup and pass in the
2924
- * flag from step data.
2925
- */
2926
- this.keysThatRemovedBaseModel = [];
2927
- /**
2928
- * A map of string to asset container which represents the currently loaded
2929
- * asset container for a given key. This allows us to know what data to unload when loading
2930
- * new data for a key.
2931
- */
2932
- this.loadedContainerForKey = new Map();
2933
- /**
2934
- * A map of string to material array which represents the currently loaded
2935
- * materials for a given key. This allows us to know what materials are in use by
2936
- * a given key.
2937
- */
2938
- this.loadedMaterialsForKey = new Map();
2939
- this.scene = scene;
2940
- this.renameClonedAsset = renameClonedAsset;
2941
- this.setBaseModelEnabled = setBaseModelEnabled;
2942
- }
2943
- /**
2944
- * Apply a material variant to a given scene.
2945
- * @param targetMaterial The name of the material in the scene we should be targeting.
2946
- * @param material The material variant to apply.
2947
- * @param onProgress A progress callback function for loading bars and event timing.
2948
- * @param removeWhenUndefined material application is an additive process, setting this bool to true will
2949
- * instead remove material textures when they aren't defined. this is useful for material editor applications
2950
- * where we want to undo changes are remove effects from display.
2951
- */
2952
- applyMaterial(targetMaterial, material, onProgress, removeWhenUndefined) {
2953
- return __awaiter(this, void 0, void 0, function* () {
2954
- return new Promise((resolve) => {
2955
- // Keep track of material changes
2956
- const existingMaterialResource = this.materialVariantMap.get(targetMaterial);
2957
- this.materialVariantMap.set(targetMaterial, Object.assign(Object.assign({}, existingMaterialResource), material));
2958
- // Rename the target to match this instance.
2959
- const targetMaterialName = this.renameClonedAsset(targetMaterial);
2960
- // Attempt to find the requested material on this object.
2961
- const targetedMaterials = this.scene.materials.filter((mat) => mat.name === targetMaterialName);
2962
- // At this point we know the scene has been loaded. If the target material doesn't exist then
2963
- // the step wasn't configured correctly to begin with so just ignore the request.
2964
- if (targetedMaterials.length === 0) {
2965
- resolve();
2966
- return;
2967
- }
2968
- // Create an async task for each type of available texture given.
2969
- const assetsManager = new AssetsManager(this.scene);
2970
- assetsManager.useDefaultLoadingScreen = false;
2971
- // Loop through the materials found in scene that match our target material name and
2972
- // notify the asset manager of the various material values that need to change on each.
2973
- targetedMaterials.forEach((targetedMaterial) => calculateMaterialProperties(material, targetedMaterial, assetsManager, removeWhenUndefined));
2974
- // Notify caller on progress towards loading material changes.
2975
- assetsManager.onProgress = (remaining, total, task) => {
2976
- onProgress && onProgress((remaining / total) * 100, 100, task.name);
2977
- };
2978
- // Execute the configured texture tasks. For each task received, we iterate ver each targeted material and
2979
- // apply the requirements of the task.
2980
- assetsManager.onFinish = (tasks) => {
2981
- tasks.forEach((task) => {
2982
- const textureTask = task;
2983
- onProgress && onProgress(100, 100, task.name);
2984
- targetedMaterials.forEach((targetMat) => applyDownloadedTexture(task.name, targetMat, material, textureTask.texture));
2985
- });
2986
- resolve();
2987
- };
2988
- assetsManager.loadAsync();
2989
- });
2990
- });
2991
- }
2992
- /**
2993
- * Applies a model variant.
2994
- * @param key The key to uniquely identify this model variant application.
2995
- * @param replaceProductModel When true, we should replace the base product model.
2996
- * @param model The details for the new model, when undefined we should remove the variant associated to the given key.
2997
- * @param onProgress A load progress callback that can be used for loading bars and event timing.
2998
- */
2999
- applyModel(key, replaceProductModel, model, onProgress) {
3000
- var _a, _b;
3001
- return __awaiter(this, void 0, void 0, function* () {
3002
- /**
3003
- * If we're adding a new model to the scene and the key hasn't been
3004
- * encountered before and the product model is being replaced, let's
3005
- * store the key so we know to replace the product model when encountered later.
3006
- */
3007
- if (model &&
3008
- replaceProductModel &&
3009
- !this.keysThatRemovedBaseModel.includes(key)) {
3010
- this.keysThatRemovedBaseModel.push(key);
3011
- }
3012
- // When no model details are provided that means
3013
- // the model variant has been requested to be removed entirely. We remove that
3014
- // and also re-add any base model if it was removed to fit this variant.
3015
- if (!model) {
3016
- if (this.keysThatRemovedBaseModel.includes(key)) {
3017
- this.setBaseModelEnabled(true);
3018
- }
3019
- (_a = this.loadedContainerForKey.get(key)) === null || _a === void 0 ? void 0 : _a.dispose();
3020
- this.loadedContainerForKey.delete(key);
3021
- this.loadedMaterialsForKey.delete(key);
3022
- return Promise.resolve(undefined);
3023
- }
3024
- // Remove any existing asset for the given key.
3025
- if (this.loadedContainerForKey.has(key)) {
3026
- (_b = this.loadedContainerForKey.get(key)) === null || _b === void 0 ? void 0 : _b.dispose();
3027
- this.loadedContainerForKey.delete(key);
3028
- this.loadedMaterialsForKey.delete(key);
3029
- }
3030
- // Remove product base model if required.
3031
- if (replaceProductModel) {
3032
- this.setBaseModelEnabled(false);
3033
- }
3034
- // Add new model to scene.
3035
- const container = yield getAssetContainer(model, this.scene, onProgress);
3036
- const instance = container.instantiateModelsToScene(this.renameClonedAsset, true);
3037
- this.loadedContainerForKey.set(key, instance);
3038
- // Store all materials used by this model.
3039
- this.loadedMaterialsForKey.set(key, getAllMaterialsForInstance(instance));
3040
- // Reapply any encountered material variants to the scene, this ensures
3041
- // no material information is lost.
3042
- const promiseList = [];
3043
- this.materialVariantMap.forEach((value, key) => __awaiter(this, void 0, void 0, function* () {
3044
- promiseList.push(this.applyMaterial(key, value));
3045
- }));
3046
- yield Promise.all(promiseList);
3047
- return instance;
3048
- });
3049
- }
3050
- dispose() {
3051
- this.loadedContainerForKey.forEach((value) => value === null || value === void 0 ? void 0 : value.dispose());
3052
- this.loadedContainerForKey.clear();
3053
- this.loadedMaterialsForKey.forEach((value) => value.forEach((mat) => mat === null || mat === void 0 ? void 0 : mat.dispose()));
3054
- this.loadedMaterialsForKey.clear();
3055
- this.materialVariantMap.clear();
3056
- this.keysThatRemovedBaseModel = [];
3057
- }
3058
- getAllMaterials() {
3059
- const materials = [];
3060
- this.loadedMaterialsForKey.forEach((value) => {
3061
- value.forEach((mat) => {
3062
- if (!materials.includes(mat)) {
3063
- materials.push(mat);
3064
- }
3065
- });
3066
- });
3067
- return materials;
3068
- }
3069
- getAnimationGroups() {
3070
- const animationGroups = [];
3071
- this.loadedContainerForKey.forEach((value) => {
3072
- animationGroups.push(...value.animationGroups);
3073
- });
3074
- return animationGroups;
3075
- }
3076
- }
3077
- function getAllMaterialsForInstance(modelInstance) {
3078
- const materials = [];
3079
- modelInstance.rootNodes.forEach((node) => {
3080
- node.getChildMeshes().forEach((mesh) => {
3081
- if (mesh.material && !materials.includes(mesh.material)) {
3082
- materials.push(mesh.material);
3083
- }
3084
- if (mesh.subMeshes) {
3085
- mesh.subMeshes.forEach((subMesh) => {
3086
- const mat = subMesh.getMaterial(false);
3087
- if (mat && !materials.includes(mat)) {
3088
- materials.push(mat);
3089
- }
3090
- });
3091
- }
3092
- });
3093
- });
3094
- return materials;
3095
- }
3096
-
3097
- export { CubeTexture as C, VariantManager as V, getAllMaterialsForInstance as g };