/
BitmapTexture2D.ts
128 lines (115 loc) · 4.55 KB
/
BitmapTexture2D.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { GPUTextureFormat } from '../gfx/graphics/webGpu/WebGPUConst';
import { LoaderBase } from '../loader/LoaderBase';
import { LoaderFunctions } from '../loader/LoaderFunctions';
import { StringUtil } from '../util/StringUtil';
import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture';
/**
* bitmap texture
* @group Texture
*/
export class BitmapTexture2D extends Texture {
private _source: HTMLCanvasElement | ImageBitmap | OffscreenCanvas | HTMLImageElement;
public premultiplyAlpha: PremultiplyAlpha = 'none';
/**
* @constructor
* @param useMipmap Set whether to use mipmap
*/
constructor(useMipmap: boolean = true) {
super();
this.useMipmap = useMipmap;
this.lodMinClamp = 0;
this.lodMaxClamp = 4;
// this.visibility = GPUShaderStage.COMPUTE | GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT;
}
/**
* get raw data of this texture
*/
public get source(): HTMLCanvasElement | ImageBitmap | OffscreenCanvas | HTMLImageElement {
return this._source;
}
/**
* set raw data of this texture
*/
public set source(value: HTMLCanvasElement | ImageBitmap | OffscreenCanvas | HTMLImageElement) {
this._source = value;
if (this._source instanceof HTMLImageElement) {
this._source.decode().then(async () => {
if (this._source instanceof HTMLImageElement) {
const imageBitmap = await createImageBitmap(this._source, { imageOrientation: this.flipY ? "flipY" : "from-image", premultiplyAlpha: 'none' });
this.generate(imageBitmap);
}
});
} else {
//@bug not generate OffscreenCanvas
if (this._source instanceof HTMLCanvasElement || this._source instanceof ImageBitmap) {
this.generate(this._source);
}
}
}
/**
* load texture data from web url
* @param url web url
* @param loaderFunctions callback function when load complete
*/
public async load(url: string, loaderFunctions?: LoaderFunctions) {
this.name = StringUtil.getURLName(url);
if (url.indexOf(';base64') != -1) {
const img = document.createElement('img');
let start = url.indexOf('data:image');
let uri = url.substring(start, url.length);
img.src = uri;
await img.decode();
img.width = Math.max(img.width, 32);
img.height = Math.max(img.height, 32);
const imageBitmap = await createImageBitmap(img, {
resizeWidth: img.width,
resizeHeight: img.height,
imageOrientation: this.flipY ? "flipY" : "from-image",
premultiplyAlpha: 'none'
});
this.format = GPUTextureFormat.rgba8unorm;
this.generate(imageBitmap);
} else {
return new Promise((succ, fial) => {
fetch(url, {
headers: Object.assign({
'Accept': 'image/avif,image/webp,*/*'
}, loaderFunctions?.headers)
}).then((r) => {
// const img = await r.blob();
// await this.loadFromBlob(img);
LoaderBase.read(url, r, loaderFunctions).then((chunks) => {
let img = new Blob([chunks], { type: 'image/jpeg' });
chunks = null;
this.loadFromBlob(img).then(() => {
succ(true);
});
});
})
})
}
return true;
}
private imageData: Blob;
/**
* load data from Blob
* @param imgData blob data which contains image
*/
public async loadFromBlob(imgData: Blob) {
this.imageData = imgData;
let imageBitmap = await createImageBitmap(imgData, { imageOrientation: this.flipY ? 'flipY' : 'from-image', premultiplyAlpha: 'none' });
if (imageBitmap.width < 32 || imageBitmap.height < 32) {
let width = Math.max(imageBitmap.width, 32);
let height = Math.max(imageBitmap.height, 32);
imageBitmap = await createImageBitmap(imageBitmap, {
resizeWidth: width,
resizeHeight: height,
imageOrientation: this.flipY ? "flipY" : "from-image",
premultiplyAlpha: 'none'
});
}
this.format = GPUTextureFormat.rgba8unorm;
this.generate(imageBitmap);
return true;
}
}