@kitware/vtk.js 34.0.0 → 34.1.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.
|
@@ -246,7 +246,14 @@ export interface vtkOpenGLTexture extends vtkViewNode {
|
|
|
246
246
|
* @param image The image to use for the texture.
|
|
247
247
|
* @returns {boolean} True if the texture was successfully created, false otherwise.
|
|
248
248
|
*/
|
|
249
|
-
create2DFromImage(image:
|
|
249
|
+
create2DFromImage(image: HTMLImageElement): boolean;
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Creates a 2D texture from an ImageBitmap.
|
|
253
|
+
* @param imageBitmap The ImageBitmap to use for the texture.
|
|
254
|
+
* @returns {boolean} True if the texture was successfully created, false otherwise.
|
|
255
|
+
*/
|
|
256
|
+
create2DFromImageBitmap(imageBitmap: ImageBitmap): boolean;
|
|
250
257
|
|
|
251
258
|
/**
|
|
252
259
|
* Creates a 2D filterable texture from raw data, with a preference for size over accuracy if necessary.
|
|
@@ -75,6 +75,19 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
75
75
|
}
|
|
76
76
|
// create the texture if it is not done already
|
|
77
77
|
if (!model.handle || model.renderable.getMTime() > model.textureBuildTime.getMTime()) {
|
|
78
|
+
if (model.renderable.getImageBitmap() !== null) {
|
|
79
|
+
if (model.renderable.getInterpolate()) {
|
|
80
|
+
model.generateMipmap = true;
|
|
81
|
+
publicAPI.setMinificationFilter(Filter.LINEAR_MIPMAP_LINEAR);
|
|
82
|
+
}
|
|
83
|
+
// Have an Image which may not be complete
|
|
84
|
+
if (model.renderable.getImageBitmap() && model.renderable.getImageLoaded()) {
|
|
85
|
+
publicAPI.create2DFromImageBitmap(model.renderable.getImageBitmap());
|
|
86
|
+
publicAPI.activate();
|
|
87
|
+
publicAPI.sendParameters();
|
|
88
|
+
model.textureBuildTime.modified();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
78
91
|
// if we have an Image
|
|
79
92
|
if (model.renderable.getImage() !== null) {
|
|
80
93
|
if (model.renderable.getInterpolate()) {
|
|
@@ -1013,7 +1026,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
1013
1026
|
|
|
1014
1027
|
//----------------------------------------------------------------------------
|
|
1015
1028
|
publicAPI.create2DFromImage = image => {
|
|
1016
|
-
//
|
|
1029
|
+
// Determine the texture parameters using the arguments.
|
|
1017
1030
|
publicAPI.getOpenGLDataType(VtkDataTypes.UNSIGNED_CHAR);
|
|
1018
1031
|
publicAPI.getInternalFormat(VtkDataTypes.UNSIGNED_CHAR, 4);
|
|
1019
1032
|
publicAPI.getFormat(VtkDataTypes.UNSIGNED_CHAR, 4);
|
|
@@ -1028,30 +1041,79 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
1028
1041
|
model._openGLRenderWindow.activateTexture(publicAPI);
|
|
1029
1042
|
publicAPI.createTexture();
|
|
1030
1043
|
publicAPI.bind();
|
|
1044
|
+
const needNearestPowerOfTwo = !model._openGLRenderWindow.getWebgl2() && (!isPowerOfTwo(image.width) || !isPowerOfTwo(image.height));
|
|
1045
|
+
let textureSource = image;
|
|
1046
|
+
let targetWidth = image.width;
|
|
1047
|
+
let targetHeight = image.height;
|
|
1048
|
+
let flipY = true;
|
|
1049
|
+
|
|
1050
|
+
// For WebGL1, we need to scale the image to the nearest power of two
|
|
1051
|
+
// dimensions if the image is not already a power of two. For WebGL2, we can
|
|
1052
|
+
// use the image as is. Note: Chrome has a perf issue where the path
|
|
1053
|
+
// HTMLImageElement -> Canvas -> texSubImage2D is faster than
|
|
1054
|
+
// HTMLImageElement -> texSubImage2D directly. See
|
|
1055
|
+
// https://issues.chromium.org/issues/41311312#comment7
|
|
1056
|
+
// Tested on Chrome 137.0.7151.104 Windows 11
|
|
1057
|
+
const isChrome = window.chrome;
|
|
1058
|
+
if (needNearestPowerOfTwo || isChrome) {
|
|
1059
|
+
const canvas = new OffscreenCanvas(nearestPowerOfTwo(image.width), nearestPowerOfTwo(image.height));
|
|
1060
|
+
targetWidth = canvas.width;
|
|
1061
|
+
targetHeight = canvas.height;
|
|
1062
|
+
const ctx = canvas.getContext('2d');
|
|
1063
|
+
ctx.translate(0, canvas.height);
|
|
1064
|
+
ctx.scale(1, -1);
|
|
1065
|
+
ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
|
|
1066
|
+
textureSource = canvas;
|
|
1067
|
+
flipY = false; // we are flipping the image manually using translate/scale
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
model.width = targetWidth;
|
|
1071
|
+
model.height = targetHeight;
|
|
1031
1072
|
|
|
1032
1073
|
// Source texture data from the PBO.
|
|
1033
|
-
|
|
1074
|
+
model.context.pixelStorei(model.context.UNPACK_FLIP_Y_WEBGL, flipY);
|
|
1034
1075
|
model.context.pixelStorei(model.context.UNPACK_ALIGNMENT, 1);
|
|
1076
|
+
if (useTexStorage(VtkDataTypes.UNSIGNED_CHAR)) {
|
|
1077
|
+
model.context.texStorage2D(model.target, 1, model.internalFormat, model.width, model.height);
|
|
1078
|
+
model.context.texSubImage2D(model.target, 0, 0, 0, model.width, model.height, model.format, model.openGLDataType, textureSource);
|
|
1079
|
+
} else {
|
|
1080
|
+
model.context.texImage2D(model.target, 0, model.internalFormat, model.width, model.height, 0, model.format, model.openGLDataType, textureSource);
|
|
1081
|
+
}
|
|
1082
|
+
if (model.generateMipmap) {
|
|
1083
|
+
model.context.generateMipmap(model.target);
|
|
1084
|
+
}
|
|
1085
|
+
model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(VtkDataTypes.UNSIGNED_CHAR, getNorm16Ext(), publicAPI.useHalfFloat());
|
|
1086
|
+
publicAPI.deactivate();
|
|
1087
|
+
return true;
|
|
1088
|
+
};
|
|
1035
1089
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
model.
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1090
|
+
//----------------------------------------------------------------------------
|
|
1091
|
+
publicAPI.create2DFromImageBitmap = imageBitmap => {
|
|
1092
|
+
// Determine the texture parameters.
|
|
1093
|
+
publicAPI.getOpenGLDataType(VtkDataTypes.UNSIGNED_CHAR);
|
|
1094
|
+
publicAPI.getInternalFormat(VtkDataTypes.UNSIGNED_CHAR, 4);
|
|
1095
|
+
publicAPI.getFormat(VtkDataTypes.UNSIGNED_CHAR, 4);
|
|
1096
|
+
if (!model.internalFormat || !model.format || !model.openGLDataType) {
|
|
1097
|
+
vtkErrorMacro('Failed to determine texture parameters.');
|
|
1098
|
+
return false;
|
|
1099
|
+
}
|
|
1100
|
+
model.target = model.context.TEXTURE_2D;
|
|
1101
|
+
model.components = 4;
|
|
1102
|
+
model.depth = 1;
|
|
1103
|
+
model.numberOfDimensions = 2;
|
|
1104
|
+
model._openGLRenderWindow.activateTexture(publicAPI);
|
|
1105
|
+
publicAPI.createTexture();
|
|
1106
|
+
publicAPI.bind();
|
|
1107
|
+
|
|
1108
|
+
// Prepare texture unpack alignment
|
|
1109
|
+
model.context.pixelStorei(model.context.UNPACK_ALIGNMENT, 1);
|
|
1110
|
+
model.width = imageBitmap.width;
|
|
1111
|
+
model.height = imageBitmap.height;
|
|
1048
1112
|
if (useTexStorage(VtkDataTypes.UNSIGNED_CHAR)) {
|
|
1049
1113
|
model.context.texStorage2D(model.target, 1, model.internalFormat, model.width, model.height);
|
|
1050
|
-
|
|
1051
|
-
model.context.texSubImage2D(model.target, 0, 0, 0, model.width, model.height, model.format, model.openGLDataType, safeImage);
|
|
1052
|
-
}
|
|
1114
|
+
model.context.texSubImage2D(model.target, 0, 0, 0, model.width, model.height, model.format, model.openGLDataType, imageBitmap);
|
|
1053
1115
|
} else {
|
|
1054
|
-
model.context.texImage2D(model.target, 0, model.internalFormat, model.width, model.height, 0, model.format, model.openGLDataType,
|
|
1116
|
+
model.context.texImage2D(model.target, 0, model.internalFormat, model.width, model.height, 0, model.format, model.openGLDataType, imageBitmap);
|
|
1055
1117
|
}
|
|
1056
1118
|
if (model.generateMipmap) {
|
|
1057
1119
|
model.context.generateMipmap(model.target);
|