bytev-charts
Version:
基于echarts和JavaScript及ES6封装的一个可以直接调用的图表组件库,内置主题设计,简单快捷,且支持用户自定义配置; npm 安装方式: npm install bytev-charts 若启动提示还需额外install插件,则运行 npm install @babel/runtime-corejs2 即可;
365 lines (323 loc) • 13.3 kB
JavaScript
import _classCallCheck from "@babel/runtime-corejs2/helpers/classCallCheck";
import _createClass from "@babel/runtime-corejs2/helpers/createClass";
import "core-js/modules/es.function.bind.js";
import "core-js/modules/es.array.join.js";
import "core-js/modules/es.math.log2.js";
import _Map from "@babel/runtime-corejs2/core-js/map";
import { GPUTextureFormat, GPUAddressMode, GPUFilterMode } from './constants.js';
import { Texture, NearestFilter, NearestMipmapNearestFilter, NearestMipmapLinearFilter, LinearFilter, RepeatWrapping, MirroredRepeatWrapping, FloatType, HalfFloatType } from '../../../../build/three.module.js';
import WebGPUTextureUtils from './WebGPUTextureUtils.js';
var WebGPUTextures = /*#__PURE__*/function () {
function WebGPUTextures(device, properties, info, glslang) {
_classCallCheck(this, WebGPUTextures);
this.device = device;
this.properties = properties;
this.info = info;
this.glslang = glslang;
this.defaultTexture = null;
this.defaultSampler = null;
this.samplerCache = new _Map();
this.utils = null;
}
_createClass(WebGPUTextures, [{
key: "getDefaultSampler",
value: function getDefaultSampler() {
if (this.defaultSampler === null) {
this.defaultSampler = this.device.createSampler({});
}
return this.defaultSampler;
}
}, {
key: "getDefaultTexture",
value: function getDefaultTexture() {
if (this.defaultTexture === null) {
this.defaultTexture = this._createTexture(new Texture());
}
return this.defaultTexture;
}
}, {
key: "getTextureGPU",
value: function getTextureGPU(texture) {
var textureProperties = this.properties.get(texture);
return textureProperties.textureGPU;
}
}, {
key: "getSampler",
value: function getSampler(texture) {
var textureProperties = this.properties.get(texture);
return textureProperties.samplerGPU;
}
}, {
key: "updateTexture",
value: function updateTexture(texture) {
var forceUpdate = false;
var textureProperties = this.properties.get(texture);
if (texture.version > 0 && textureProperties.version !== texture.version) {
var image = texture.image;
if (image === undefined) {
console.warn('THREE.WebGPURenderer: Texture marked for update but image is undefined.');
} else if (image.complete === false) {
console.warn('THREE.WebGPURenderer: Texture marked for update but image is incomplete.');
} else {
// texture init
if (textureProperties.initialized === undefined) {
textureProperties.initialized = true;
var disposeCallback = onTextureDispose.bind(this);
textureProperties.disposeCallback = disposeCallback;
texture.addEventListener('dispose', disposeCallback);
this.info.memory.textures++;
} // texture creation
if (textureProperties.textureGPU !== undefined) {
// @TODO: Avoid calling of destroy() in certain scenarios. When only the contents of a texture
// are updated, a buffer upload should be sufficient. However, if the user changes
// the dimensions of the texture, format or usage, a new instance of GPUTexture is required.
textureProperties.textureGPU.destroy();
}
textureProperties.textureGPU = this._createTexture(texture);
textureProperties.version = texture.version;
forceUpdate = true;
}
} // if the texture is used for RTT, it's necessary to init it once so the binding
// group's resource definition points to the respective GPUTexture
if (textureProperties.initializedRTT === false) {
textureProperties.initializedRTT = true;
forceUpdate = true;
}
return forceUpdate;
}
}, {
key: "updateSampler",
value: function updateSampler(texture) {
var array = [];
array.push(texture.wrapS);
array.push(texture.wrapT);
array.push(texture.wrapR);
array.push(texture.magFilter);
array.push(texture.minFilter);
array.push(texture.anisotropy);
var key = array.join();
var samplerGPU = this.samplerCache.get(key);
if (samplerGPU === undefined) {
samplerGPU = this.device.createSampler({
addressModeU: this._convertAddressMode(texture.wrapS),
addressModeV: this._convertAddressMode(texture.wrapT),
addressModeW: this._convertAddressMode(texture.wrapR),
magFilter: this._convertFilterMode(texture.magFilter),
minFilter: this._convertFilterMode(texture.minFilter),
mipmapFilter: this._convertFilterMode(texture.minFilter),
maxAnisotropy: texture.anisotropy
});
this.samplerCache.set(key, samplerGPU);
}
var textureProperties = this.properties.get(texture);
textureProperties.samplerGPU = samplerGPU;
}
}, {
key: "initRenderTarget",
value: function initRenderTarget(renderTarget) {
var properties = this.properties;
var renderTargetProperties = properties.get(renderTarget);
if (renderTargetProperties.initialized === undefined) {
var device = this.device;
var width = renderTarget.width;
var height = renderTarget.height;
var colorTextureGPU = device.createTexture({
size: {
width: width,
height: height,
depth: 1
},
format: GPUTextureFormat.BRGA8Unorm,
// @TODO: Make configurable
usage: GPUTextureUsage.OUTPUT_ATTACHMENT | GPUTextureUsage.SAMPLED
});
renderTargetProperties.colorTextureGPU = colorTextureGPU; // When the ".texture" or ".depthTexture" property of a render target is used as a map,
// the renderer has to find the respective GPUTexture objects to setup the bind groups.
// Since it's not possible to see just from a texture object whether it belongs to a render
// target or not, we need the initializedRTT flag.
var textureProperties = properties.get(renderTarget.texture);
textureProperties.textureGPU = colorTextureGPU;
textureProperties.initializedRTT = false;
if (renderTarget.depthBuffer === true) {
var depthTextureGPU = device.createTexture({
size: {
width: width,
height: height,
depth: 1
},
format: GPUTextureFormat.Depth24PlusStencil8,
// @TODO: Make configurable
usage: GPUTextureUsage.OUTPUT_ATTACHMENT
});
renderTargetProperties.depthTextureGPU = depthTextureGPU;
if (renderTarget.depthTexture !== null) {
var depthTextureProperties = properties.get(renderTarget.depthTexture);
depthTextureProperties.textureGPU = depthTextureGPU;
depthTextureProperties.initializedRTT = false;
}
}
renderTargetProperties.initialized = true;
}
}
}, {
key: "dispose",
value: function dispose() {
this.samplerCache.clear();
}
}, {
key: "_computeMipLevelCount",
value: function _computeMipLevelCount(width, height) {
return Math.floor(Math.log2(Math.max(width, height))) + 1;
}
}, {
key: "_convertAddressMode",
value: function _convertAddressMode(value) {
var addressMode = GPUAddressMode.ClampToEdge;
if (value === RepeatWrapping) {
addressMode = GPUAddressMode.Repeat;
} else if (value === MirroredRepeatWrapping) {
addressMode = GPUAddressMode.MirrorRepeat;
}
return addressMode;
}
}, {
key: "_convertFilterMode",
value: function _convertFilterMode(value) {
var filterMode = GPUFilterMode.Linear;
if (value === NearestFilter || value === NearestMipmapNearestFilter || value === NearestMipmapLinearFilter) {
filterMode = GPUFilterMode.Nearest;
}
return filterMode;
}
}, {
key: "_convertFormat",
value: function _convertFormat(type) {
var formatGPU = GPUTextureFormat.RGBA8Unorm;
if (type === FloatType) {
formatGPU = GPUTextureFormat.RGBA32Float;
} else if (type === HalfFloatType) {
formatGPU = GPUTextureFormat.RGBA16Float;
}
return formatGPU;
}
}, {
key: "_createTexture",
value: function _createTexture(texture) {
var _this = this;
var device = this.device;
var image = texture.image;
var width = image !== undefined ? image.width : 1;
var height = image !== undefined ? image.height : 1;
var format = this._convertFormat(texture.type);
var needsMipmaps = this._needsMipmaps(texture);
var mipLevelCount = needsMipmaps === true ? this._computeMipLevelCount(width, height) : undefined;
var usage = GPUTextureUsage.SAMPLED | GPUTextureUsage.COPY_DST;
if (needsMipmaps === true) {
usage |= GPUTextureUsage.OUTPUT_ATTACHMENT;
} // texture creation
var textureGPUDescriptor = {
size: {
width: width,
height: height,
depth: 1
},
format: format,
usage: usage,
mipLevelCount: mipLevelCount
};
var textureGPU = device.createTexture(textureGPUDescriptor); // transfer texture data
if (texture.isDataTexture) {
this._copyBufferToTexture(image, format, textureGPU);
} else {
// convert HTML iamges and canvas elements to ImageBitmap before copy
if (typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement) {
var options = {};
options.imageOrientation = texture.flipY === true ? 'flipY' : 'none';
options.premultiplyAlpha = texture.premultiplyAlpha === true ? 'premultiply' : 'default';
createImageBitmap(image, 0, 0, width, height, options).then(function (imageBitmap) {
_this._copyImageBitmapToTexture(imageBitmap, textureGPU, needsMipmaps, textureGPUDescriptor);
});
} else {
if (image !== undefined) {
// assuming ImageBitmap. Directly start copy operation of the contents of ImageBitmap into the destination texture
this._copyImageBitmapToTexture(image, textureGPU, needsMipmaps, textureGPUDescriptor);
}
}
}
return textureGPU;
}
}, {
key: "_copyBufferToTexture",
value: function _copyBufferToTexture(image, format, textureGPU) {
// this code assumes data textures in RGBA format
// @TODO: Consider to support valid buffer layouts with other formats like RGB
// @TODO: Support mipmaps
var device = this.device;
var data = image.data;
var bytesPerTexel = this._getBytesPerTexel(format);
var bytesPerRow = Math.ceil(image.width * bytesPerTexel / 256) * 256;
var textureDataBuffer = device.createBuffer({
size: data.byteLength,
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,
mappedAtCreation: true
});
new data.constructor(textureDataBuffer.getMappedRange()).set(data);
textureDataBuffer.unmap();
var commandEncoder = device.createCommandEncoder({});
commandEncoder.copyBufferToTexture({
buffer: textureDataBuffer,
bytesPerRow: bytesPerRow
}, {
texture: textureGPU
}, {
width: image.width,
height: image.height,
depth: 1
});
device.defaultQueue.submit([commandEncoder.finish()]);
textureDataBuffer.destroy();
}
}, {
key: "_copyImageBitmapToTexture",
value: function _copyImageBitmapToTexture(imageBitmap, textureGPU, needsMipmaps, textureGPUDescriptor) {
var device = this.device;
device.defaultQueue.copyImageBitmapToTexture({
imageBitmap: imageBitmap
}, {
texture: textureGPU
}, {
width: imageBitmap.width,
height: imageBitmap.height,
depth: 1
});
if (needsMipmaps === true) {
if (this.utils === null) {
this.utils = new WebGPUTextureUtils(this.device, this.glslang); // only create this helper if necessary
}
this.utils.generateMipmappedTexture(imageBitmap, textureGPU, textureGPUDescriptor);
}
}
}, {
key: "_getBytesPerTexel",
value: function _getBytesPerTexel(format) {
if (format === GPUTextureFormat.RGBA8Unorm) return 4;
if (format === GPUTextureFormat.RGBA16Float) return 8;
if (format === GPUTextureFormat.RGBA32Float) return 16;
}
}, {
key: "_needsMipmaps",
value: function _needsMipmaps(texture) {
return texture.generateMipmaps === true && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
}
}]);
return WebGPUTextures;
}();
function onTextureDispose(event) {
var texture = event.target;
var textureProperties = this.properties.get(texture);
textureProperties.textureGPU.destroy();
texture.removeEventListener('dispose', textureProperties.disposeCallback);
this.properties.remove(texture);
this.info.memory.textures--;
}
export default WebGPUTextures;