Skip to content
29 changes: 27 additions & 2 deletions Examples/Rendering/LabelmapEdgeProjection/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@ const { BlendMode } = Constants;
* New Blend Mode: [LABELMAP_EDGE_PROJECTION_BLEND]
*
*/
const viewAPI =
new URLSearchParams(window.location.search).get('viewAPI') || 'WebGL';

const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
background: [0, 0, 0],
defaultViewAPI: viewAPI,
});
const renderer = fullScreenRenderer.getRenderer();
const renderWindow = fullScreenRenderer.getRenderWindow();
Expand All @@ -53,18 +57,31 @@ actor.setMapper(mapper);
// ----------------------------------------------------------------------------
const gui = new GUI();
const guiParams = {
viewAPI,
blendMode: 'regular',
thickness1: 3,
thickness2: 3,
};

gui
.add(guiParams, 'viewAPI', ['WebGL', 'WebGPU'])
.name('Renderer')
.onChange((api) => {
const query = new URLSearchParams(window.location.search);
query.set('viewAPI', api);
window.location.search = query.toString();
});

let imageData;
let dims;
let center;
let radius1;
let radius2;
let edgeLabelmapActor = null;
let regularLabelmapActor = null;
// pristine single component scalars of the base image; both blend modes
// rebuild their scalar array from this copy so switching stays repeatable
let baseScalarData = null;

// ----------------------------------------------------------------------------
// Common functions
Expand Down Expand Up @@ -164,8 +181,7 @@ function createRegularLabelmap(imgData, d, c, r1, r2) {
}

function createAdvancedMIPLabelmap(imgData, d, c, r1, r2) {
const array = imgData.getPointData().getArray(0);
const baseData = array.getData();
const baseData = baseScalarData;

const numberOfComponents = 2;
const cubeData = new Float32Array(numberOfComponents * baseData.length);
Expand Down Expand Up @@ -217,6 +233,14 @@ function createBasePipeline() {
renderer.removeVolume(actor);
mapper.setInputData(imageData);

// restore the pristine single component scalars and the default color mix
// (edge mode replaces them with a two component image + labels array and
// the additive preset)
const array = imageData.getPointData().getArray(0);
array.setData(baseScalarData);
array.setNumberOfComponents(1);
actor.getProperty().setColorMixPreset(ColorMixPreset.DEFAULT);

renderer.addVolume(actor);
setupTransferFunctions();

Expand Down Expand Up @@ -296,6 +320,7 @@ const reader = vtkHttpDataSetReader.newInstance({ fetchGzip: true });
reader.setUrl(`${__BASE_PATH__}/data/volume/LIDC2.vti`).then(() => {
reader.loadData().then(() => {
imageData = reader.getOutputData();
baseScalarData = imageData.getPointData().getArray(0).getData().slice();

dims = imageData.getDimensions();
center = dims.map((d) => Math.floor(d / 2));
Expand Down
12 changes: 12 additions & 0 deletions Examples/Volume/VolumeMapperBlendModes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import '@kitware/vtk.js/IO/Core/DataAccessHelper/JSZipDataAccessHelper';

import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow';
import vtkHttpDataSetReader from '@kitware/vtk.js/IO/Core/HttpDataSetReader';
import vtkURLExtract from '@kitware/vtk.js/Common/Core/URLExtract';
import vtkPiecewiseFunction from '@kitware/vtk.js/Common/DataModel/PiecewiseFunction';
import vtkColorTransferFunction from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction';
import vtkVolume from '@kitware/vtk.js/Rendering/Core/Volume';
Expand All @@ -20,6 +21,9 @@ import GUI from 'lil-gui';
// Standard rendering code setup
// ----------------------------------------------------------------------------

const userParms = vtkURLExtract.extractURLParameters();
const viewAPI = userParms.viewAPI || 'WebGL';

const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
background: [0.3, 0.3, 0.3],
});
Expand All @@ -33,6 +37,7 @@ const gui = new GUI();
// ----------------------------------------------------------------------------
// UI params
const params = {
viewAPI,
BlendMode: 5,
IpScalarMin: 0.0,
IpScalarMax: 1.0,
Expand All @@ -45,6 +50,13 @@ const params = {
const reader = vtkHttpDataSetReader.newInstance({ fetchGzip: true });
const initialSampleDistance = 1.3;

gui
.add(params, 'viewAPI', ['WebGL', 'WebGPU'])
.name('Renderer')
.onChange((api) => {
window.location = `?viewAPI=${api}`;
});

const actor = vtkVolume.newInstance();
const actorProperty = actor.getProperty();
const mapper = vtkVolumeMapper.newInstance();
Expand Down
4 changes: 2 additions & 2 deletions Sources/Rendering/Core/HardwareSelector/example/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import '@kitware/vtk.js/favicon';

// Load the rendering pieces we want to use (for both WebGL and WebGPU)
import '@kitware/vtk.js/Rendering/Profiles/Geometry';
import '@kitware/vtk.js/Rendering/OpenGL/Glyph3DMapper';
import '@kitware/vtk.js/Rendering/Profiles/Glyph';

import { throttle } from '@kitware/vtk.js/macros';
import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
Expand Down Expand Up @@ -340,7 +340,7 @@ function processSelections(selections) {
// Selecting cells
const cellPoints = input.getCellPoints(attributeID);
updateAssociationTooltip('Cell', attributeID);
if (cellPoints) {
if (cellPoints?.cellPointIds) {
const pointIds = cellPoints.cellPointIds;
// Find the closest cell point, and use that as cursor position
const points = Array.from(pointIds).map((pointId) =>
Expand Down
14 changes: 14 additions & 0 deletions Sources/Rendering/Core/VolumeMapper/example/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import vtkMath from '@kitware/vtk.js/Common/Core/Math';
import vtkPiecewiseFunction from '@kitware/vtk.js/Common/DataModel/PiecewiseFunction';
import vtkProperty from '@kitware/vtk.js/Rendering/Core/Property';
import vtkSphereSource from '@kitware/vtk.js/Filters/Sources/SphereSource';
import vtkURLExtract from '@kitware/vtk.js/Common/Core/URLExtract';
import vtkVolume from '@kitware/vtk.js/Rendering/Core/Volume';
import vtkVolumeMapper from '@kitware/vtk.js/Rendering/Core/VolumeMapper';

Expand All @@ -30,8 +31,12 @@ const { Representation, Shading } = vtkProperty;
// Standard rendering code setup
// ----------------------------------------------------------------------------

const userParams = vtkURLExtract.extractURLParameters();
const viewAPI = userParams.viewAPI || 'WebGL';

const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
background: [0, 0, 0],
defaultViewAPI: viewAPI,
});
const renderer = fullScreenRenderer.getRenderer();
const renderWindow = fullScreenRenderer.getRenderWindow();
Expand All @@ -51,6 +56,7 @@ let volumeController;
let presetController;
let forceNearestControllers = [];
const params = {
viewAPI,
ParallelProjection: false,
Lighting: true,
LAO: false,
Expand Down Expand Up @@ -271,6 +277,14 @@ reader.setUrl(`${__BASE_PATH__}/data/volume/LIDC2.vti`).then(() => {

// TEST ==============

gui
.add(params, 'viewAPI', ['WebGL', 'WebGPU'])
.name('Renderer')
.onChange((api) => {
const query = new URLSearchParams(window.location.search);
query.set('viewAPI', api);
window.location.search = query.toString();
});
gui
.add(params, 'ParallelProjection')
.name('Parallel Projection')
Expand Down
10 changes: 10 additions & 0 deletions Sources/Rendering/WebGPU/CellArrayMapper/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,12 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
model.UBO.setArray('BCWCMatrix', keyMats.bcwc);
model.UBO.setArray('BCSCMatrix', keyMats.bcsc);
model.UBO.setArray('MCWCNormals', keyMats.normalMatrix);
const bufferShift = model.WebGPUActor.getBufferShift(model.WebGPURenderer);
model.UBO.setArray('BufferShift', [
bufferShift[0],
bufferShift[1],
bufferShift[2],
]);

// --- 2D or 3D ---
if (model.is2D) {
Expand Down Expand Up @@ -1807,6 +1813,10 @@ export function extend(publicAPI, model, initiaLalues = {}) {
model.UBO.addEntry('Time', 'u32');
addClipPlaneEntries(model.UBO, 'ClipPlane');
model.UBO.addEntry('NumClipPlanes', 'u32');
// Coordinate shift baked into the point buffer (vertexBC = modelCoord +
// BufferShift). Exposed so mappers that transform vertices before BCSCMatrix
// (e.g. the glyph mapper's per instance matrix) can recover raw model coords.
model.UBO.addEntry('BufferShift', 'vec3<f32>');

// Build VTK API
macro.setGet(publicAPI, model, [
Expand Down
24 changes: 21 additions & 3 deletions Sources/Rendering/WebGPU/Glyph3DMapper/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import vtkWebGPUCellArrayMapper from 'vtk.js/Sources/Rendering/WebGPU/CellArrayM
import vtkWebGPUPolyDataMapper from 'vtk.js/Sources/Rendering/WebGPU/PolyDataMapper';
import vtkWebGPUStorageBuffer from 'vtk.js/Sources/Rendering/WebGPU/StorageBuffer';
import vtkWebGPUShaderCache from 'vtk.js/Sources/Rendering/WebGPU/ShaderCache';
import { getClipPlaneShaderChecks } from 'vtk.js/Sources/Rendering/WebGPU/Helpers/ClippingPlanes';
import { registerOverride } from 'vtk.js/Sources/Rendering/WebGPU/ViewNodeFactory';

function vtkWebGPUGlyph3DCellArrayMapper(publicAPI, model) {
Expand Down Expand Up @@ -32,13 +33,30 @@ function vtkWebGPUGlyph3DCellArrayMapper(publicAPI, model) {
vDesc.addBuiltinInput('u32', '@builtin(instance_index) instanceIndex');
vDesc.addBuiltinOutput('vec4<f32>', '@builtin(position) Position');
if (!vDesc.hasOutput('vertexVC')) vDesc.addOutput('vec3<f32>', 'vertexVC');
if (!vDesc.hasOutput('vertexSC')) vDesc.addOutput('vec4<f32>', 'vertexSC');
let code = vDesc.getCode();
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Position::Impl', [
' var vertexSC: vec4<f32> = mapperUBO.BCSCMatrix*glyphSSBO.values[input.instanceIndex].matrix*vertexBC;',
' output.vertexVC = (rendererUBO.SCVCMatrix*vertexSC).xyz;',
' output.Position = rendererUBO.SCPCMatrix*vertexSC;',
' var glyphMC: vec4<f32> = vec4<f32>(vertexBC.xyz - mapperUBO.BufferShift, 1.0);',
' var glyphModel: vec4<f32> = glyphSSBO.values[input.instanceIndex].matrix*glyphMC;',
' var glyphBC: vec4<f32> = vec4<f32>(glyphModel.xyz + mapperUBO.BufferShift, 1.0);',
' output.vertexSC = mapperUBO.BCSCMatrix*glyphBC;',
' output.vertexVC = (rendererUBO.SCVCMatrix*output.vertexSC).xyz;',
' output.Position = rendererUBO.SCPCMatrix*output.vertexSC;',
]).result;
vDesc.setCode(code);

const fDesc = pipeline.getShaderDescription('fragment');
let fcode = fDesc.getCode();
const clipPlaneChecks = getClipPlaneShaderChecks({
countName: 'mapperUBO.NumClipPlanes',
planePrefix: 'mapperUBO.ClipPlane',
positionName: 'input.vertexSC',
});
fcode = vtkWebGPUShaderCache.substitute(fcode, '//VTK::Position::Impl', [
...clipPlaneChecks,
'//VTK::Position::Impl',
]).result;
fDesc.setCode(fcode);
};
model.shaderReplacements.set(
'replaceShaderPosition',
Expand Down
Loading
Loading