@acransac/vtk.js
Version:
Visualization Toolkit for the Web
140 lines (119 loc) • 4.46 kB
JavaScript
import macro from 'vtk.js/Sources/macro';
import vtkWebGPUBufferManager from 'vtk.js/Sources/Rendering/WebGPU/BufferManager';
const { BufferUsage } = vtkWebGPUBufferManager;
// const { ObjectType } = Constants;
// ----------------------------------------------------------------------------
// Global methods
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// vtkWebGPUTexture methods
// ----------------------------------------------------------------------------
function vtkWebGPUTexture(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkWebGPUTexture');
publicAPI.create = (device, options) => {
model.device = device;
model.width = options.width;
model.height = options.height;
model.depth = options.depth;
model.handle = model.device.getHandle().createTexture({
size: [options.width, options.height, options.depth],
format: options.format, // 'rgba8unorm',
/* eslint-disable no-undef */
/* eslint-disable no-bitwise */
usage: GPUTextureUsage.SAMPLED | GPUTextureUsage.COPY_DST,
/* eslint-enable no-undef */
/* eslint-enable no-bitwise */
});
};
// set the data
publicAPI.writeImageData = (idata) => {
if (idata.isA && idata.isA('vtkImageData')) {
// create and write the buffer
const buffRequest = {
dataArray: idata.getPointData().getScalars(),
time: idata.getPointData().getScalars().getMTime(),
/* eslint-disable no-undef */
usage: BufferUsage.Texture,
/* eslint-enable no-undef */
format: 'unorm8x4',
};
const buff = model.device.getBufferManager().getBuffer(buffRequest);
model.buffer = buff;
// get a buffer for the image (todo move into texture manager)
const cmdEnc = model.device.createCommandEncoder();
cmdEnc.copyBufferToTexture(
{
buffer: model.buffer.getHandle(),
// layout: {
offset: 0,
bytesPerRow: 4 * model.width,
rowsPerImage: model.height,
// },
},
{ texture: model.handle },
[model.width, model.height, model.depth]
);
model.device.submitCommandEncoder(cmdEnc);
model.ready = true;
} else {
const canvas = document.createElement('canvas');
canvas.width = idata.width;
canvas.height = idata.height;
const ctx = canvas.getContext('2d');
ctx.translate(0, canvas.height);
ctx.scale(1, -1);
ctx.drawImage(
idata,
0,
0,
idata.width,
idata.height,
0,
0,
canvas.width,
canvas.height
);
// In Chrome 69 on Windows and Ubuntu, there is a bug that prevents some
// canvases from working properly with webGL textures. By getting any
// image data from the canvas, this works around the bug. See
// https://bugs.chromium.org/p/chromium/issues/detail?id=896307
if (navigator.userAgent.indexOf('Chrome/69') >= 0) {
ctx.getImageData(0, 0, 1, 1);
}
const safeImage = canvas;
createImageBitmap(safeImage).then((imageBitmap) => {
model.device
.getHandle()
.queue.copyImageBitmapToTexture(
{ imageBitmap },
{ texture: model.handle },
[model.width, model.height, model.depth]
);
model.ready = true;
});
}
};
}
// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
const DEFAULT_VALUES = {
device: null,
handle: null,
buffer: null,
ready: false,
};
// ----------------------------------------------------------------------------
export function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);
// Object methods
macro.obj(publicAPI, model);
macro.get(publicAPI, model, ['handle', 'ready']);
macro.setGet(publicAPI, model, ['device']);
vtkWebGPUTexture(publicAPI, model);
}
// ----------------------------------------------------------------------------
export const newInstance = macro.newInstance(extend);
// ----------------------------------------------------------------------------
export default { newInstance, extend };