Skip to content

Commit

Permalink
fix: Fix update of color and opacity textures
Browse files Browse the repository at this point in the history
BREAKING CHANGE: getTransferFunctionHash becomes getTransferFunctionsHash
It takes a list of functions as argument instead of a single function
Also ImageResliceMapper doesn't wieght color using mix.
  • Loading branch information
bruyeret committed Oct 3, 2024
1 parent 14649a2 commit 132be4b
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 93 deletions.
54 changes: 34 additions & 20 deletions Sources/Rendering/OpenGL/ImageCPRMapper/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import vtkShaderProgram from 'vtk.js/Sources/Rendering/OpenGL/ShaderProgram';
import vtkViewNode from 'vtk.js/Sources/Rendering/SceneGraph/ViewNode';

import {
getTransferFunctionHash,
getTransferFunctionsHash,
getImageDataHash,
} from 'vtk.js/Sources/Rendering/OpenGL/RenderWindow/resourceSharingHelper';

Expand Down Expand Up @@ -243,15 +243,21 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
const numIComps = iComps ? numComp : 1;
const textureHeight = iComps ? 2 * numIComps : 1;

const colorTransferFunc = ppty.getRGBTransferFunction();
const colorTextureHash = getTransferFunctionHash(
colorTransferFunc,
const colorTransferFunctions = [];
for (let component = 0; component < numIComps; ++component) {
colorTransferFunctions.push(ppty.getRGBTransferFunction(component));
}
const colorTextureHash = getTransferFunctionsHash(
colorTransferFunctions,
iComps,
numIComps
);

const firstColorTransferFunc = ppty.getRGBTransferFunction();
const cachedColorEntry =
model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
model._openGLRenderWindow.getGraphicsResourceForObject(
firstColorTransferFunc
);
const reBuildColorTexture =
!cachedColorEntry?.oglObject?.getHandle() ||
cachedColorEntry?.hash !== colorTextureHash;
Expand All @@ -261,7 +267,7 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
const cTable = new Uint8ClampedArray(cSize);
model.colorTexture = vtkOpenGLTexture.newInstance();
model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
if (colorTransferFunc) {
if (firstColorTransferFunc) {
const tmpTable = new Float32Array(cWidth * 3);

for (let c = 0; c < numIComps; c++) {
Expand Down Expand Up @@ -303,23 +309,23 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
);
}

if (colorTransferFunc) {
if (firstColorTransferFunc) {
model._openGLRenderWindow.setGraphicsResourceForObject(
colorTransferFunc,
firstColorTransferFunc,
model.colorTexture,
colorTextureHash
);
if (colorTransferFunc !== model._colorTransferFunc) {
if (firstColorTransferFunc !== model._colorTransferFunc) {
model._openGLRenderWindow.registerGraphicsResourceUser(
colorTransferFunc,
firstColorTransferFunc,
publicAPI
);
model._openGLRenderWindow.unregisterGraphicsResourceUser(
model._colorTransferFunc,
publicAPI
);
}
model._colorTransferFunc = colorTransferFunc;
model._colorTransferFunc = firstColorTransferFunc;
}
} else {
model.colorTexture = cachedColorEntry.oglObject;
Expand All @@ -328,10 +334,18 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
// Build piecewise function buffer. This buffer is used either
// for component weighting or opacity, depending on whether we're
// rendering components independently or not.
const pwFunc = ppty.getPiecewiseFunction();
const pwfTextureHash = getTransferFunctionHash(pwFunc, iComps, numIComps);
const opacityFunctions = [];
for (let component = 0; component < numIComps; ++component) {
opacityFunctions.push(ppty.getPiecewiseFunction(component));
}
const pwfTextureHash = getTransferFunctionsHash(
opacityFunctions,
iComps,
numIComps
);
const firstPwFunc = ppty.getPiecewiseFunction();
const cachedPwfEntry =
model._openGLRenderWindow.getGraphicsResourceForObject(pwFunc);
model._openGLRenderWindow.getGraphicsResourceForObject(firstPwFunc);
const reBuildPwf =
!cachedPwfEntry?.oglObject?.getHandle() ||
cachedPwfEntry?.hash !== pwfTextureHash;
Expand All @@ -341,7 +355,7 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
const pwfTable = new Uint8ClampedArray(pwfSize);
model.pwfTexture = vtkOpenGLTexture.newInstance();
model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
if (pwFunc) {
if (firstPwFunc) {
const pwfFloatTable = new Float32Array(pwfSize);
const tmpTable = new Float32Array(pwfWidth);

Expand Down Expand Up @@ -386,23 +400,23 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
pwfTable
);
}
if (pwFunc) {
if (firstPwFunc) {
model._openGLRenderWindow.setGraphicsResourceForObject(
pwFunc,
firstPwFunc,
model.pwfTexture,
pwfTextureHash
);
if (pwFunc !== model._pwFunc) {
if (firstPwFunc !== model._pwFunc) {
model._openGLRenderWindow.registerGraphicsResourceUser(
pwFunc,
firstPwFunc,
publicAPI
);
model._openGLRenderWindow.unregisterGraphicsResourceUser(
model._pwFunc,
publicAPI
);
}
model._pwFunc = pwFunc;
model._pwFunc = firstPwFunc;
}
} else {
model.pwfTexture = cachedPwfEntry.oglObject;
Expand Down
57 changes: 36 additions & 21 deletions Sources/Rendering/OpenGL/ImageMapper/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from 'vtk.js/Sources/Rendering/OpenGL/Texture/Constants';
import { InterpolationType } from 'vtk.js/Sources/Rendering/Core/ImageProperty/Constants';

import { getTransferFunctionHash } from 'vtk.js/Sources/Rendering/OpenGL/RenderWindow/resourceSharingHelper';
import { getTransferFunctionsHash } from 'vtk.js/Sources/Rendering/OpenGL/RenderWindow/resourceSharingHelper';

import vtkPolyDataVS from 'vtk.js/Sources/Rendering/OpenGL/glsl/vtkPolyDataVS.glsl';
import vtkPolyDataFS from 'vtk.js/Sources/Rendering/OpenGL/glsl/vtkPolyDataFS.glsl';
Expand Down Expand Up @@ -931,14 +931,21 @@ function vtkOpenGLImageMapper(publicAPI, model) {
const numIComps = iComps ? numComp : 1;
const textureHeight = iComps ? 2 * numIComps : 1;

const colorTransferFunc = actorProperty.getRGBTransferFunction();
const cfunToString = getTransferFunctionHash(
colorTransferFunc,
const colorTransferFunctions = [];
for (let component = 0; component < numIComps; ++component) {
colorTransferFunctions.push(
actorProperty.getRGBTransferFunction(component)
);
}
const cfunToString = getTransferFunctionsHash(
colorTransferFunctions,
iComps,
numIComps
);
const cTex =
model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
const firstColorTransferFunc = actorProperty.getRGBTransferFunction();
const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(
firstColorTransferFunc
);

const reBuildC =
!cTex?.oglObject?.getHandle() || cTex?.hash !== cfunToString;
Expand All @@ -959,7 +966,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
model.colorTexture.setMagnificationFilter(Filter.LINEAR);
}

if (colorTransferFunc) {
if (firstColorTransferFunc) {
const tmpTable = new Float32Array(cWidth * 3);

for (let c = 0; c < numIComps; c++) {
Expand Down Expand Up @@ -1000,23 +1007,23 @@ function vtkOpenGLImageMapper(publicAPI, model) {
);
}

if (colorTransferFunc) {
if (firstColorTransferFunc) {
model._openGLRenderWindow.setGraphicsResourceForObject(
colorTransferFunc,
firstColorTransferFunc,
model.colorTexture,
cfunToString
);
if (colorTransferFunc !== model._colorTransferFunc) {
if (firstColorTransferFunc !== model._colorTransferFunc) {
model._openGLRenderWindow.registerGraphicsResourceUser(
colorTransferFunc,
firstColorTransferFunc,
publicAPI
);
model._openGLRenderWindow.unregisterGraphicsResourceUser(
model._colorTransferFunc,
publicAPI
);
}
model._colorTransferFunc = colorTransferFunc;
model._colorTransferFunc = firstColorTransferFunc;
}
} else {
model.colorTexture = cTex.oglObject;
Expand All @@ -1025,10 +1032,18 @@ function vtkOpenGLImageMapper(publicAPI, model) {
// Build piecewise function buffer. This buffer is used either
// for component weighting or opacity, depending on whether we're
// rendering components independently or not.
const pwFunc = actorProperty.getPiecewiseFunction();
const pwfunToString = getTransferFunctionHash(pwFunc, iComps, numIComps);
const opacityFunctions = [];
for (let component = 0; component < numIComps; ++component) {
opacityFunctions.push(actorProperty.getPiecewiseFunction(component));
}
const pwfunToString = getTransferFunctionsHash(
opacityFunctions,
iComps,
numIComps
);
const firstPwFunc = actorProperty.getPiecewiseFunction();
const pwfTex =
model._openGLRenderWindow.getGraphicsResourceForObject(pwFunc);
model._openGLRenderWindow.getGraphicsResourceForObject(firstPwFunc);
// rebuild opacity tfun?
const reBuildPwf =
!pwfTex?.oglObject?.getHandle() || pwfTex?.hash !== pwfunToString;
Expand All @@ -1049,7 +1064,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
model.pwfTexture.setMagnificationFilter(Filter.LINEAR);
}

if (pwFunc) {
if (firstPwFunc) {
const pwfFloatTable = new Float32Array(pwfSize);
const tmpTable = new Float32Array(pwfWidth);

Expand Down Expand Up @@ -1094,23 +1109,23 @@ function vtkOpenGLImageMapper(publicAPI, model) {
);
}

if (pwFunc) {
if (firstPwFunc) {
model._openGLRenderWindow.setGraphicsResourceForObject(
pwFunc,
firstPwFunc,
model.pwfTexture,
pwfunToString
);
if (pwFunc !== model._pwFunc) {
if (firstPwFunc !== model._pwFunc) {
model._openGLRenderWindow.registerGraphicsResourceUser(
pwFunc,
firstPwFunc,
publicAPI
);
model._openGLRenderWindow.unregisterGraphicsResourceUser(
model._pwFunc,
publicAPI
);
}
model._pwFunc = pwFunc;
model._pwFunc = firstPwFunc;
}
} else {
model.pwfTexture = pwfTex.oglObject;
Expand Down
55 changes: 35 additions & 20 deletions Sources/Rendering/OpenGL/ImageResliceMapper/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import vtkTransform from 'vtk.js/Sources/Common/Transform/Transform';
import vtkViewNode from 'vtk.js/Sources/Rendering/SceneGraph/ViewNode';

import {
getTransferFunctionHash,
getTransferFunctionsHash,
getImageDataHash,
} from 'vtk.js/Sources/Rendering/OpenGL/RenderWindow/resourceSharingHelper';

Expand Down Expand Up @@ -341,14 +341,21 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
const numIComps = iComps ? model.numberOfComponents : 1;
const textureHeight = iComps ? 2 * numIComps : 1;

const colorTransferFunc = firstActorProperty.getRGBTransferFunction();
const colorFuncHash = getTransferFunctionHash(
colorTransferFunc,
const colorTransferFunctions = [];
for (let component = 0; component < numIComps; ++component) {
colorTransferFunctions.push(
firstActorProperty.getRGBTransferFunction(component)
);
}
const colorFuncHash = getTransferFunctionsHash(
colorTransferFunctions,
iComps,
numIComps
);
const cTex =
model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
const firstColorTransferFunc = firstActorProperty.getRGBTransferFunction();
const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(
firstColorTransferFunc
);
const reBuildC =
!cTex?.oglObject?.getHandle() || cTex?.hash !== colorFuncHash;
if (reBuildC) {
Expand All @@ -357,7 +364,7 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
const cTable = new Uint8ClampedArray(cSize);
const newColorTexture = vtkOpenGLTexture.newInstance();
newColorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
if (colorTransferFunc) {
if (firstColorTransferFunc) {
const tmpTable = new Float32Array(cWidth * 3);

for (let c = 0; c < numIComps; c++) {
Expand Down Expand Up @@ -403,9 +410,9 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
);
}

if (colorTransferFunc) {
if (firstColorTransferFunc) {
model._openGLRenderWindow.setGraphicsResourceForObject(
colorTransferFunc,
firstColorTransferFunc,
newColorTexture,
colorFuncHash
);
Expand All @@ -417,17 +424,25 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
replaceGraphicsResource(
model._openGLRenderWindow,
model._colorTextureCore,
colorTransferFunc
firstColorTransferFunc
);
model._colorTextureCore = colorTransferFunc;
model._colorTextureCore = firstColorTransferFunc;

// Build piecewise function buffer. This buffer is used either
// for component weighting or opacity, depending on whether we're
// rendering components independently or not.
const pwFunc = firstActorProperty.getPiecewiseFunction();
const opacityFuncHash = getTransferFunctionHash(pwFunc, iComps, numIComps);
const opacityFunctions = [];
for (let component = 0; component < numIComps; ++component) {
opacityFunctions.push(firstActorProperty.getPiecewiseFunction(component));
}
const opacityFuncHash = getTransferFunctionsHash(
opacityFunctions,
iComps,
numIComps
);
const firstPwFunc = firstActorProperty.getPiecewiseFunction();
const pwfTex =
model._openGLRenderWindow.getGraphicsResourceForObject(pwFunc);
model._openGLRenderWindow.getGraphicsResourceForObject(firstPwFunc);
const reBuildPwf =
!pwfTex?.oglObject?.getHandle() || pwfTex?.hash !== opacityFuncHash;
if (reBuildPwf) {
Expand All @@ -436,7 +451,7 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
const pwfTable = new Uint8ClampedArray(pwfSize);
const newOpacityTexture = vtkOpenGLTexture.newInstance();
newOpacityTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
if (pwFunc) {
if (firstPwFunc) {
const pwfFloatTable = new Float32Array(pwfSize);
const tmpTable = new Float32Array(pwfWidth);

Expand Down Expand Up @@ -481,9 +496,9 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
pwfTable
);
}
if (pwFunc) {
if (firstPwFunc) {
model._openGLRenderWindow.setGraphicsResourceForObject(
pwFunc,
firstPwFunc,
newOpacityTexture,
opacityFuncHash
);
Expand All @@ -495,9 +510,9 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
replaceGraphicsResource(
model._openGLRenderWindow,
model._pwfTextureCore,
pwFunc
firstPwFunc
);
model._pwfTextureCore = pwFunc;
model._pwfTextureCore = firstPwFunc;

const vboString = `${model.resliceGeom.getMTime()}A${model.renderable.getSlabThickness()}`;
if (
Expand Down Expand Up @@ -1098,7 +1113,7 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
const rgba = ['r', 'g', 'b', 'a'];
for (let comp = 0; comp < tNumComp; ++comp) {
tcoordFSImpl = tcoordFSImpl.concat([
`vec3 tcolor${comp} = mix${comp} * texture2D(colorTexture1, vec2(tvalue.${rgba[comp]} * cscale${comp} + cshift${comp}, height${comp})).rgb;`,
`vec3 tcolor${comp} = texture2D(colorTexture1, vec2(tvalue.${rgba[comp]} * cscale${comp} + cshift${comp}, height${comp})).rgb;`,
`float compWeight${comp} = mix${comp} * texture2D(pwfTexture1, vec2(tvalue.${rgba[comp]} * pwfscale${comp} + pwfshift${comp}, height${comp})).r;`,
]);
}
Expand Down
Loading

0 comments on commit 132be4b

Please sign in to comment.