@kitware/vtk.js 25.1.3 → 25.2.2

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.
@@ -1,18 +1,41 @@
1
1
  import { mat4, vec3 } from 'gl-matrix';
2
2
  import { newInstance as newInstance$1, obj, get, getArray, setGet, vtkDebugMacro as vtkDebugMacro$1 } from '../../macros.js';
3
+ import { r as radiansFromDegrees } from '../../Common/Core/Math/index.js';
3
4
  import vtkViewNode from '../SceneGraph/ViewNode.js';
4
5
  import vtkWebGPUBindGroup from './BindGroup.js';
5
6
  import vtkWebGPUFullScreenQuad from './FullScreenQuad.js';
7
+ import vtkWebGPUStorageBuffer from './StorageBuffer.js';
6
8
  import vtkWebGPUUniformBuffer from './UniformBuffer.js';
7
9
  import { registerOverride } from './ViewNodeFactory.js';
8
10
 
9
11
  var vtkDebugMacro = vtkDebugMacro$1;
10
- var clearFragTemplate = "\n//VTK::Renderer::Dec\n\n//VTK::Mapper::Dec\n\n//VTK::TCoord::Dec\n\n//VTK::RenderEncoder::Dec\n\n//VTK::IOStructs::Dec\n\n@fragment\nfn main(\n//VTK::IOStructs::Input\n)\n//VTK::IOStructs::Output\n{\n var output: fragmentOutput;\n\n var computedColor: vec4<f32> = mapperUBO.BackgroundColor;\n\n //VTK::RenderEncoder::Impl\n return output;\n}\n"; // ----------------------------------------------------------------------------
12
+ var clearFragTemplate = "\n//VTK::Renderer::Dec\n\n//VTK::Mapper::Dec\n\n//VTK::TCoord::Dec\n\n//VTK::RenderEncoder::Dec\n\n//VTK::IOStructs::Dec\n\n@fragment\nfn main(\n//VTK::IOStructs::Input\n)\n//VTK::IOStructs::Output\n{\n var output: fragmentOutput;\n\n var computedColor: vec4<f32> = mapperUBO.BackgroundColor;\n\n //VTK::RenderEncoder::Impl\n return output;\n}\n"; // Light type index gives either 0, 1, or 2 which indicates what type of light there is.
13
+ // While technically, there are only spot and directional lights, within the CellArrayMapper
14
+ // there is a third, positional light. It is technically just a variant of a spot light with
15
+ // a cone angle of 90 or above, however certain calculations can be skipped if it is treated
16
+ // separately.
17
+ // The mappings are shown below:
18
+ // 0 -> positional light
19
+ // 1 -> directional light
20
+ // 2 -> spot light
21
+
22
+ function getLightTypeIndex(light) {
23
+ if (light.getPositional()) {
24
+ if (light.getConeAngle() >= 90) {
25
+ return 0;
26
+ }
27
+
28
+ return 2;
29
+ }
30
+
31
+ return 1;
32
+ } // ----------------------------------------------------------------------------
11
33
  // vtkWebGPURenderer methods
12
34
  // ----------------------------------------------------------------------------
13
35
 
14
36
  /* eslint-disable no-bitwise */
15
37
 
38
+
16
39
  function vtkWebGPURenderer(publicAPI, model) {
17
40
  // Set our className
18
41
  model.classHierarchy.push('vtkWebGPURenderer'); // Builds myself.
@@ -108,6 +131,7 @@ function vtkWebGPURenderer(publicAPI, model) {
108
131
  model.UBO.setArray('SCVCMatrix', keyMats.scvc);
109
132
  model.UBO.setArray('VCPCMatrix', keyMats.vcpc);
110
133
  model.UBO.setArray('WCVCNormals', keyMats.normalMatrix);
134
+ model.UBO.setValue('LightCount', model.renderable.getLights().length);
111
135
  var tsize = publicAPI.getYInvertedTiledSizeAndOrigin();
112
136
  model.UBO.setArray('viewportSize', [tsize.usize, tsize.vsize]);
113
137
  model.UBO.setValue('cameraParallel', model.camera.getParallelProjection());
@@ -118,6 +142,79 @@ function vtkWebGPURenderer(publicAPI, model) {
118
142
  }
119
143
  };
120
144
 
145
+ publicAPI.updateSSBO = function () {
146
+ var lights = model.renderable.getLights();
147
+ var keyMats = model.webgpuCamera.getKeyMatrices(publicAPI);
148
+ var lightTimeString = "".concat(model.renderable.getMTime());
149
+
150
+ for (var i = 0; i < lights.length; i++) {
151
+ lightTimeString += lights[i].getMTime();
152
+ }
153
+
154
+ if (lightTimeString !== model.lightTimeString) {
155
+ var lightPosArray = new Float32Array(lights.length * 4);
156
+ var lightDirArray = new Float32Array(lights.length * 4);
157
+ var lightColorArray = new Float32Array(lights.length * 4);
158
+ var lightTypeArray = new Float32Array(lights.length * 4);
159
+
160
+ for (var _i = 0; _i < lights.length; _i++) {
161
+ var offset = _i * 4; // Position
162
+
163
+ var viewCoordinatePosition = lights[_i].getPosition();
164
+
165
+ vec3.transformMat4(viewCoordinatePosition, viewCoordinatePosition, keyMats.wcvc); // console.log(viewCoordinatePosition);
166
+ // viewCoordinatePosition
167
+
168
+ lightPosArray[offset] = viewCoordinatePosition[0];
169
+ lightPosArray[offset + 1] = viewCoordinatePosition[1];
170
+ lightPosArray[offset + 2] = viewCoordinatePosition[2];
171
+ lightPosArray[offset + 3] = 0; // Rotation (All are negative to correct for -Z being forward)
172
+
173
+ lightDirArray[offset] = -lights[_i].getDirection()[0];
174
+ lightDirArray[offset + 1] = -lights[_i].getDirection()[1];
175
+ lightDirArray[offset + 2] = -lights[_i].getDirection()[2];
176
+ lightDirArray[offset + 3] = 0; // Color
177
+
178
+ lightColorArray[offset] = lights[_i].getColor()[0];
179
+ lightColorArray[offset + 1] = lights[_i].getColor()[1];
180
+ lightColorArray[offset + 2] = lights[_i].getColor()[2];
181
+ lightColorArray[offset + 3] = lights[_i].getIntensity() * 5; // arbitrary multiplication to fix the dullness of low value PBR lights
182
+ // Type
183
+
184
+ lightTypeArray[offset] = getLightTypeIndex(lights[_i]); // Type
185
+
186
+ lightTypeArray[offset + 1] = Math.cos(radiansFromDegrees(lights[_i].getConeAngle())); // Inner Phi, should probably do some check on these to make sure they dont excede limits
187
+
188
+ lightTypeArray[offset + 2] = Math.cos(radiansFromDegrees(lights[_i].getConeAngle() + lights[_i].getConeFalloff())); // Outer Phi
189
+
190
+ lightTypeArray[offset + 3] = 0;
191
+ } // Im not sure how correct this is, but this is what the example does
192
+ // https://kitware.github.io/vtk-js/api/Rendering_WebGPU_VolumePassFSQ.html
193
+
194
+
195
+ model.SSBO.clearData();
196
+ model.SSBO.setNumberOfInstances(lights.length);
197
+ model.SSBO.addEntry('LightPos', 'vec4<f32>'); // Position
198
+
199
+ model.SSBO.addEntry('LightDir', 'vec4<f32>'); // Direction
200
+
201
+ model.SSBO.addEntry('LightColor', 'vec4<f32>'); // Color (r, g, b, intensity)
202
+
203
+ model.SSBO.addEntry('LightData', 'vec4<f32>'); // Other data (type, etc, etc, etc)
204
+
205
+ model.SSBO.setAllInstancesFromArray('LightPos', lightPosArray);
206
+ model.SSBO.setAllInstancesFromArray('LightDir', lightDirArray);
207
+ model.SSBO.setAllInstancesFromArray('LightColor', lightColorArray);
208
+ model.SSBO.setAllInstancesFromArray('LightData', lightTypeArray);
209
+
210
+ var device = model._parent.getDevice();
211
+
212
+ model.SSBO.send(device);
213
+ }
214
+
215
+ model.lightTimeString = lightTimeString;
216
+ };
217
+
121
218
  publicAPI.scissorAndViewport = function (encoder) {
122
219
  var tsize = publicAPI.getYInvertedTiledSizeAndOrigin();
123
220
  encoder.getHandle().setViewport(tsize.lowerLeftU, tsize.lowerLeftV, tsize.usize, tsize.vsize, 0.0, 1.0); // set scissor
@@ -134,6 +231,7 @@ function vtkWebGPURenderer(publicAPI, model) {
134
231
  if (prepass) {
135
232
  model.renderEncoder.begin(model._parent.getCommandEncoder());
136
233
  publicAPI.updateUBO();
234
+ publicAPI.updateSSBO();
137
235
  } else {
138
236
  publicAPI.scissorAndViewport(model.renderEncoder);
139
237
  publicAPI.clear();
@@ -284,7 +382,8 @@ function extend(publicAPI, model) {
284
382
  var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
285
383
  Object.assign(model, DEFAULT_VALUES, initialValues); // Inheritance
286
384
 
287
- vtkViewNode.extend(publicAPI, model, initialValues);
385
+ vtkViewNode.extend(publicAPI, model, initialValues); // UBO
386
+
288
387
  model.UBO = vtkWebGPUUniformBuffer.newInstance({
289
388
  label: 'rendererUBO'
290
389
  });
@@ -295,11 +394,17 @@ function extend(publicAPI, model) {
295
394
  model.UBO.addEntry('VCPCMatrix', 'mat4x4<f32>');
296
395
  model.UBO.addEntry('WCVCNormals', 'mat4x4<f32>');
297
396
  model.UBO.addEntry('viewportSize', 'vec2<f32>');
298
- model.UBO.addEntry('cameraParallel', 'u32');
397
+ model.UBO.addEntry('LightCount', 'i32');
398
+ model.UBO.addEntry('cameraParallel', 'u32'); // SSBO (Light data)
399
+
400
+ model.SSBO = vtkWebGPUStorageBuffer.newInstance({
401
+ label: 'rendererLightSSBO'
402
+ });
403
+ model.lightTimeString = '';
299
404
  model.bindGroup = vtkWebGPUBindGroup.newInstance({
300
405
  label: 'rendererBG'
301
406
  });
302
- model.bindGroup.setBindables([model.UBO]);
407
+ model.bindGroup.setBindables([model.UBO, model.SSBO]);
303
408
  model.tmpMat4 = mat4.identity(new Float64Array(16));
304
409
  model.stabilizedTime = {};
305
410
  obj(model.stabilizedTime, {
@@ -176,7 +176,12 @@ function vtkWebGPUSimpleMapper(publicAPI, model) {
176
176
  publicAPI.draw = function (renderEncoder) {
177
177
  var pipeline = renderEncoder.getBoundPipeline(); // bind the mapper bind group
178
178
 
179
- renderEncoder.activateBindGroup(model.bindGroup); // bind the vertex input
179
+ renderEncoder.activateBindGroup(model.bindGroup);
180
+
181
+ if (model.WebGPURenderer) {
182
+ model.WebGPURenderer.bindUBO(renderEncoder);
183
+ } // bind the vertex input
184
+
180
185
 
181
186
  pipeline.bindVertexInput(renderEncoder, model.vertexInput);
182
187
  var indexBuffer = model.vertexInput.getIndexBuffer();
@@ -222,7 +227,6 @@ function vtkWebGPUSimpleMapper(publicAPI, model) {
222
227
 
223
228
  if (model.WebGPURenderer) {
224
229
  model.pipeline.addBindGroupLayout(model.WebGPURenderer.getBindGroup());
225
- model.pipeline.addDrawCallback(model.WebGPURenderer.bindUBO);
226
230
  }
227
231
 
228
232
  model.pipeline.addBindGroupLayout(model.bindGroup);
@@ -7,7 +7,7 @@ import { registerOverride } from './ViewNodeFactory.js';
7
7
 
8
8
  var BufferUsage = vtkWebGPUBufferManager.BufferUsage;
9
9
  var vtkErrorMacro = vtkErrorMacro$1;
10
- var vtkWebGPUSphereMapperVS = "\n//VTK::Renderer::Dec\n\n//VTK::Mapper::Dec\n\n//VTK::Color::Dec\n\n//VTK::IOStructs::Dec\n\n@vertex\nfn main(\n//VTK::IOStructs::Input\n)\n//VTK::IOStructs::Output\n{\n var output : vertexOutput;\n\n var vertexVC: vec4<f32> = rendererUBO.SCVCMatrix * mapperUBO.BCSCMatrix * vec4<f32>(vertexBC.x, vertexBC.y, vertexBC.z, 1.0);\n\n //VTK::Color::Impl\n\n // compute the projected vertex position\n output.centerVC = vertexVC.xyz;\n output.radiusVC = length(offsetMC)*0.5;\n\n // make the triangle face the camera\n if (rendererUBO.cameraParallel == 0u)\n {\n var dir: vec3<f32> = normalize(-vertexVC.xyz);\n var base2: vec3<f32> = normalize(cross(dir,vec3<f32>(1.0,0.0,0.0)));\n var base1: vec3<f32> = cross(base2,dir);\n dir = vertexVC.xyz + offsetMC.x*base1 + offsetMC.y*base2;\n vertexVC = vec4<f32>(dir, 1.0);\n }\n else\n {\n // add in the offset\n var tmp2: vec2<f32> = vertexVC.xy + offsetMC;\n vertexVC = vec4<f32>(tmp2, vertexVC.zw);\n }\n\n output.vertexVC = vertexVC.xyz;\n\n //VTK::Position::Impl\n\n return output;\n}\n"; // ----------------------------------------------------------------------------
10
+ var vtkWebGPUSphereMapperVS = "\n//VTK::Renderer::Dec\n\n//VTK::Mapper::Dec\n\n//VTK::Color::Dec\n\n//VTK::IOStructs::Dec\n\n@vertex\nfn main(\n//VTK::IOStructs::Input\n)\n//VTK::IOStructs::Output\n{\n var output : vertexOutput;\n\n var vertexVC: vec4<f32> = rendererUBO.SCVCMatrix * mapperUBO.BCSCMatrix * vec4<f32>(vertexBC.xyz, 1.0);\n\n //VTK::Color::Impl\n\n // compute the projected vertex position\n output.centerVC = vertexVC.xyz;\n output.radiusVC = length(offsetMC)*0.5;\n\n // make the triangle face the camera\n if (rendererUBO.cameraParallel == 0u)\n {\n var dir: vec3<f32> = normalize(-vertexVC.xyz);\n var base2: vec3<f32> = normalize(cross(dir,vec3<f32>(1.0,0.0,0.0)));\n var base1: vec3<f32> = cross(base2,dir);\n dir = vertexVC.xyz + offsetMC.x*base1 + offsetMC.y*base2;\n vertexVC = vec4<f32>(dir, 1.0);\n }\n else\n {\n // add in the offset\n var tmp2: vec2<f32> = vertexVC.xy + offsetMC;\n vertexVC = vec4<f32>(tmp2, vertexVC.zw);\n }\n\n output.vertexVC = vec4<f32>(vertexVC.xyz, 0.0);\n\n //VTK::Position::Impl\n\n return output;\n}\n"; // ----------------------------------------------------------------------------
11
11
  // vtkWebGPUSphereMapper methods
12
12
  // ----------------------------------------------------------------------------
13
13
 
@@ -32,7 +32,7 @@ function vtkWebGPUSphereMapper(publicAPI, model) {
32
32
 
33
33
  publicAPI.replaceShaderNormal = function (hash, pipeline, vertexInput) {
34
34
  var vDesc = pipeline.getShaderDescription('vertex');
35
- vDesc.addOutput('vec3<f32>', 'vertexVC');
35
+ if (!vDesc.hasOutput('vertexVC')) vDesc.addOutput('vec4<f32>', 'vertexVC');
36
36
  vDesc.addOutput('vec3<f32>', 'centerVC');
37
37
  vDesc.addOutput('f32', 'radiusVC');
38
38
  var fDesc = pipeline.getShaderDescription('fragment');
@@ -26,7 +26,7 @@ var vtkErrorMacro = vtkErrorMacro$1; // Vertices
26
26
  // 4: 011
27
27
  // 5: 111
28
28
 
29
- var vtkWebGPUStickMapperVS = "\n//VTK::Renderer::Dec\n\n//VTK::Mapper::Dec\n\n//VTK::Color::Dec\n\n//VTK::IOStructs::Dec\n\n@vertex\nfn main(\n//VTK::IOStructs::Input\n)\n//VTK::IOStructs::Output\n{\n var offsetsArray: array<vec3<f32>, 12> = array<vec3<f32>, 12>(\n vec3<f32>(-1.0, -1.0, -1.0),\n vec3<f32>(1.0, -1.0, -1.0),\n vec3<f32>(1.0, -1.0, 1.0),\n\n vec3<f32>(-1.0, -1.0, -1.0),\n vec3<f32>(1.0, -1.0, 1.0),\n vec3<f32>(-1.0, -1.0, 1.0),\n\n vec3<f32>(-1.0, -1.0, 1.0),\n vec3<f32>(1.0, -1.0, 1.0),\n vec3<f32>(1.0, 1.0, 1.0),\n\n vec3<f32>(-1.0, -1.0, 1.0),\n vec3<f32>(1.0, 1.0, 1.0),\n vec3<f32>(-1.0, 1.0, 1.0)\n );\n\n var output : vertexOutput;\n\n var vertexVC: vec4<f32> = rendererUBO.SCVCMatrix * mapperUBO.BCSCMatrix * vec4<f32>(vertexBC.x, vertexBC.y, vertexBC.z, 1.0);\n\n //VTK::Color::Impl\n\n // compute the projected vertex position\n output.centerVC = vertexVC.xyz;\n output.radiusVC = radiusMC;\n output.lengthVC = length(orientMC);\n output.orientVC = (rendererUBO.WCVCNormals * vec4<f32>(normalize(orientMC), 0.0)).xyz;\n\n // make sure it is pointing out of the screen\n if (output.orientVC.z < 0.0)\n {\n output.orientVC = -output.orientVC;\n }\n\n // make the basis\n var xbase: vec3<f32>;\n var ybase: vec3<f32>;\n var dir: vec3<f32> = vec3<f32>(0.0,0.0,1.0);\n if (rendererUBO.cameraParallel == 0u)\n {\n dir = normalize(-vertexVC.xyz);\n }\n if (abs(dot(dir,output.orientVC)) == 1.0)\n {\n xbase = normalize(cross(vec3<f32>(0.0,1.0,0.0),output.orientVC));\n ybase = cross(xbase,output.orientVC);\n }\n else\n {\n xbase = normalize(cross(output.orientVC,dir));\n ybase = cross(output.orientVC,xbase);\n }\n\n\n var vertIdx: u32 = input.vertexIndex % 12u;\n var offsets: vec3<f32> = offsetsArray[vertIdx];\n\n vertexVC = vec4<f32>(vertexVC.xyz +\n output.radiusVC * offsets.x * xbase +\n output.radiusVC * offsets.y * ybase +\n 0.5 * output.lengthVC * offsets.z * output.orientVC, 1.0);\n\n output.vertexVC = vertexVC;\n\n //VTK::Position::Impl\n\n return output;\n}\n"; // ----------------------------------------------------------------------------
29
+ var vtkWebGPUStickMapperVS = "\n//VTK::Renderer::Dec\n\n//VTK::Mapper::Dec\n\n//VTK::Color::Dec\n\n//VTK::IOStructs::Dec\n\n@vertex\nfn main(\n//VTK::IOStructs::Input\n)\n//VTK::IOStructs::Output\n{\n var offsetsArray: array<vec3<f32>, 12> = array<vec3<f32>, 12>(\n vec3<f32>(-1.0, -1.0, -1.0),\n vec3<f32>(1.0, -1.0, -1.0),\n vec3<f32>(1.0, -1.0, 1.0),\n\n vec3<f32>(-1.0, -1.0, -1.0),\n vec3<f32>(1.0, -1.0, 1.0),\n vec3<f32>(-1.0, -1.0, 1.0),\n\n vec3<f32>(-1.0, -1.0, 1.0),\n vec3<f32>(1.0, -1.0, 1.0),\n vec3<f32>(1.0, 1.0, 1.0),\n\n vec3<f32>(-1.0, -1.0, 1.0),\n vec3<f32>(1.0, 1.0, 1.0),\n vec3<f32>(-1.0, 1.0, 1.0)\n );\n\n var output : vertexOutput;\n\n var vertexVC: vec4<f32> = rendererUBO.SCVCMatrix * mapperUBO.BCSCMatrix * vec4<f32>(vertexBC.xyz, 1.0);\n\n //VTK::Color::Impl\n\n // compute the projected vertex position\n output.centerVC = vertexVC.xyz;\n output.radiusVC = radiusMC;\n output.lengthVC = length(orientMC);\n output.orientVC = (rendererUBO.WCVCNormals * vec4<f32>(normalize(orientMC), 0.0)).xyz;\n\n // make sure it is pointing out of the screen\n if (output.orientVC.z < 0.0)\n {\n output.orientVC = -output.orientVC;\n }\n\n // make the basis\n var xbase: vec3<f32>;\n var ybase: vec3<f32>;\n var dir: vec3<f32> = vec3<f32>(0.0,0.0,1.0);\n if (rendererUBO.cameraParallel == 0u)\n {\n dir = normalize(-vertexVC.xyz);\n }\n if (abs(dot(dir,output.orientVC)) == 1.0)\n {\n xbase = normalize(cross(vec3<f32>(0.0,1.0,0.0),output.orientVC));\n ybase = cross(xbase,output.orientVC);\n }\n else\n {\n xbase = normalize(cross(output.orientVC,dir));\n ybase = cross(output.orientVC,xbase);\n }\n\n\n var vertIdx: u32 = input.vertexIndex % 12u;\n var offsets: vec3<f32> = offsetsArray[vertIdx];\n\n vertexVC = vec4<f32>(vertexVC.xyz +\n output.radiusVC * offsets.x * xbase +\n output.radiusVC * offsets.y * ybase +\n 0.5 * output.lengthVC * offsets.z * output.orientVC, 1.0);\n\n output.vertexVC = vertexVC;\n\n //VTK::Position::Impl\n\n return output;\n}\n"; // ----------------------------------------------------------------------------
30
30
  // vtkWebGPUStickMapper methods
31
31
  // ----------------------------------------------------------------------------
32
32
 
@@ -51,7 +51,7 @@ function vtkWebGPUStickMapper(publicAPI, model) {
51
51
 
52
52
  publicAPI.replaceShaderNormal = function (hash, pipeline, vertexInput) {
53
53
  var vDesc = pipeline.getShaderDescription('vertex');
54
- vDesc.addOutput('vec4<f32>', 'vertexVC');
54
+ if (!vDesc.hasOutput('vertexVC')) vDesc.addOutput('vec4<f32>', 'vertexVC');
55
55
  vDesc.addOutput('vec3<f32>', 'centerVC');
56
56
  vDesc.addOutput('vec3<f32>', 'orientVC');
57
57
  vDesc.addOutput('f32', 'radiusVC');
@@ -184,8 +184,12 @@ function vtkWebGPUTexture(publicAPI, model) {
184
184
  return tDetails.numComponents;
185
185
  };
186
186
 
187
- publicAPI.getDimensions = function () {
188
- return model.depth > 1 ? 3 : 2;
187
+ publicAPI.getDimensionality = function () {
188
+ var dims = 0;
189
+ if (model.width > 1) dims++;
190
+ if (model.height > 1) dims++;
191
+ if (model.depth > 1) dims++;
192
+ return dims;
189
193
  };
190
194
 
191
195
  publicAPI.resizeToMatch = function (tex) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitware/vtk.js",
3
- "version": "25.1.3",
3
+ "version": "25.2.2",
4
4
  "description": "Visualization Toolkit for the Web",
5
5
  "keywords": [
6
6
  "3d",