Skip to content

Commit

Permalink
Merge pull request #500 from Kitware/better_intermixed_depth
Browse files Browse the repository at this point in the history
fix(Rendering): fix imagemapper depth pass
  • Loading branch information
martinken authored Jan 12, 2018
2 parents 2deb74a + e42ea23 commit 85622e1
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 6 deletions.
36 changes: 36 additions & 0 deletions Sources/Rendering/OpenGL/ImageMapper/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ function vtkOpenGLImageMapper(publicAPI, model) {
}
};

publicAPI.opaqueZBufferPass = (prepass) => {
if (prepass) {
model.haveSeenDepthRequest = true;
model.renderDepth = true;
publicAPI.render();
model.renderDepth = false;
}
};

publicAPI.opaquePass = (prepass) => {
if (prepass) {
publicAPI.render();
Expand Down Expand Up @@ -109,6 +118,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
'//VTK::TCoord::Dec',
'attribute vec2 tcoordMC; varying vec2 tcoordVCVSOutput;'
).result;

FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Dec', [
'varying vec2 tcoordVCVSOutput;',
'uniform float shift;',
Expand Down Expand Up @@ -150,6 +160,22 @@ function vtkOpenGLImageMapper(publicAPI, model) {
]
).result;
}

if (model.haveSeenDepthRequest) {
FSSource = vtkShaderProgram.substitute(
FSSource,
'//VTK::ZBuffer::Dec',
'uniform int depthRequest;'
).result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ZBuffer::Impl', [
'if (depthRequest == 1) {',
'float iz = floor(gl_FragCoord.z*65535.0 + 0.1);',
'float rf = floor(iz/256.0)/255.0;',
'float gf = mod(iz,256.0)/255.0;',
'gl_FragData[0] = vec4(rf, gf, 0.0, 1.0); }',
]).result;
}

shaders.Vertex = VSSource;
shaders.Fragment = FSSource;
};
Expand All @@ -161,11 +187,13 @@ function vtkOpenGLImageMapper(publicAPI, model) {
// input modified
// light complexity changed
if (
model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest ||
cellBO.getProgram() === 0 ||
cellBO.getShaderSourceTime().getMTime() < publicAPI.getMTime() ||
cellBO.getShaderSourceTime().getMTime() < actor.getMTime() ||
cellBO.getShaderSourceTime().getMTime() < model.currentInput.getMTime()
) {
model.lastHaveSeenDepthRequest = model.haveSeenDepthRequest;
return true;
}

Expand Down Expand Up @@ -277,6 +305,12 @@ function vtkOpenGLImageMapper(publicAPI, model) {
const scale = oglShiftScale.scale / cw;
const shift = (oglShiftScale.shift - cl) / cw + 0.5;

if (model.haveSeenDepthRequest) {
cellBO
.getProgram()
.setUniformi('depthRequest', model.renderDepth ? 1 : 0);
}

cellBO.getProgram().setUniformf('shift', shift);
cellBO.getProgram().setUniformf('scale', scale);

Expand Down Expand Up @@ -614,6 +648,8 @@ const DEFAULT_VALUES = {
tris: null,
imagemat: null,
colorTexture: null,
lastHaveSeenDepthRequest: false,
haveSeenDepthRequest: false,
};

// ----------------------------------------------------------------------------
Expand Down
26 changes: 20 additions & 6 deletions Sources/Rendering/OpenGL/PolyDataMapper/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ function vtkOpenGLPolyDataMapper(publicAPI, model) {

publicAPI.opaqueZBufferPass = (prepass) => {
if (prepass) {
model.haveSeenDepthRequest = true;
model.renderDepth = true;
publicAPI.render();
model.renderDepth = false;
Expand Down Expand Up @@ -1007,13 +1008,19 @@ function vtkOpenGLPolyDataMapper(publicAPI, model) {
publicAPI.replaceShaderCoincidentOffset(shaders, ren, actor);
publicAPI.replaceShaderPositionVC(shaders, ren, actor);

if (model.renderDepth) {
if (model.haveSeenDepthRequest) {
let FSSource = shaders.Fragment;
FSSource = vtkShaderProgram.substitute(
FSSource,
'//VTK::ZBuffer::Dec',
'uniform int depthRequest;'
).result;
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ZBuffer::Impl', [
'if (depthRequest == 1) {',
'float iz = floor(gl_FragCoord.z*65535.0 + 0.1);',
'float rf = floor(iz/256.0)/255.0;',
'float gf = mod(iz,256.0)/255.0;',
'gl_FragData[0] = vec4(rf, gf, 0.0, 1.0);',
'gl_FragData[0] = vec4(rf, gf, 0.0, 1.0); }',
]).result;
shaders.Fragment = FSSource;
}
Expand Down Expand Up @@ -1102,23 +1109,21 @@ function vtkOpenGLPolyDataMapper(publicAPI, model) {
needRebuild = true;
}

const toString = `${model.renderDepth}`;

// has something changed that would require us to recreate the shader?
// candidates are
// property modified (representation interpolation and lighting)
// input modified
// light complexity changed
if (
model.shaderRebuildString !== toString ||
model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest ||
cellBO.getProgram() === 0 ||
cellBO.getShaderSourceTime().getMTime() < publicAPI.getMTime() ||
cellBO.getShaderSourceTime().getMTime() < actor.getMTime() ||
cellBO.getShaderSourceTime().getMTime() < model.renderable.getMTime() ||
cellBO.getShaderSourceTime().getMTime() < model.currentInput.getMTime() ||
needRebuild
) {
model.shaderRebuildString = toString;
model.lastHaveSeenDepthRequest = model.haveSeenDepthRequest;
return true;
}

Expand Down Expand Up @@ -1327,6 +1332,13 @@ function vtkOpenGLPolyDataMapper(publicAPI, model) {
}
}

// handle depth requests
if (model.haveSeenDepthRequest) {
cellBO
.getProgram()
.setUniformi('depthRequest', model.renderDepth ? 1 : 0);
}

// handle coincident
if (cellBO.getProgram().isUniformUsed('coffset')) {
const cp = publicAPI.getCoincidentParameters(ren, actor);
Expand Down Expand Up @@ -1876,6 +1888,8 @@ const DEFAULT_VALUES = {
lightColor: [], // used internally
lightHalfAngle: [], // used internally
lightDirection: [], // used internally
lastHaveSeenDepthRequest: false,
haveSeenDepthRequest: false,
};

// ----------------------------------------------------------------------------
Expand Down
111 changes: 111 additions & 0 deletions Sources/Rendering/OpenGL/VolumeMapper/test/testIntermixedImage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import test from 'tape-catch';
import testUtils from 'vtk.js/Sources/Testing/testUtils';

import vtkColorTransferFunction from 'vtk.js/Sources/Rendering/Core/ColorTransferFunction';
import vtkHttpDataSetReader from 'vtk.js/Sources/IO/Core/HttpDataSetReader';
import vtkImageGridSource from 'vtk.js/Sources/Filters/Sources/ImageGridSource';
import vtkImageMapper from 'vtk.js/Sources/Rendering/Core/ImageMapper';
import vtkImageSlice from 'vtk.js/Sources/Rendering/Core/ImageSlice';
import vtkOpenGLRenderWindow from 'vtk.js/Sources/Rendering/OpenGL/RenderWindow';
import vtkPiecewiseFunction from 'vtk.js/Sources/Common/DataModel/PiecewiseFunction';
import vtkRenderWindow from 'vtk.js/Sources/Rendering/Core/RenderWindow';
import vtkRenderWindowInteractor from 'vtk.js/Sources/Rendering/Core/RenderWindowInteractor';
import vtkRenderer from 'vtk.js/Sources/Rendering/Core/Renderer';
import vtkVolume from 'vtk.js/Sources/Rendering/Core/Volume';
import vtkVolumeMapper from 'vtk.js/Sources/Rendering/Core/VolumeMapper';

import baseline1 from './testIntermixedImage.png';

test.onlyIfWebGL('Test Composite Volume Rendering', (t) => {
const gc = testUtils.createGarbageCollector(t);
t.ok('rendering', 'vtkOpenGLVolumeMapper IntermixedImage');
// testUtils.keepDOM();

// Create some control UI
const container = document.querySelector('body');
const renderWindowContainer = gc.registerDOMElement(
document.createElement('div')
);
container.appendChild(renderWindowContainer);

// create what we will view
const renderWindow = gc.registerResource(vtkRenderWindow.newInstance());
const renderer = gc.registerResource(vtkRenderer.newInstance());
renderWindow.addRenderer(renderer);
renderer.setBackground(0.32, 0.3, 0.43);

const volume = gc.registerResource(vtkVolume.newInstance());

const vmapper = gc.registerResource(vtkVolumeMapper.newInstance());
vmapper.setSampleDistance(0.7);
volume.setMapper(vmapper);

const reader = vtkHttpDataSetReader.newInstance({ fetchGzip: true });
// create color and opacity transfer functions
const ctfun = vtkColorTransferFunction.newInstance();
ctfun.addRGBPoint(0, 85 / 255.0, 0, 0);
ctfun.addRGBPoint(95, 1.0, 1.0, 1.0);
ctfun.addRGBPoint(225, 0.66, 0.66, 0.5);
ctfun.addRGBPoint(255, 0.3, 1.0, 0.5);
const ofun = vtkPiecewiseFunction.newInstance();
ofun.addPoint(0.0, 0.0);
ofun.addPoint(255.0, 1.0);
volume.getProperty().setRGBTransferFunction(0, ctfun);
volume.getProperty().setScalarOpacity(0, ofun);
volume.getProperty().setScalarOpacityUnitDistance(0, 3.0);
volume.getProperty().setInterpolationTypeToFastLinear();

vmapper.setInputConnection(reader.getOutputPort());

// now create something to view it, in this case webgl
const glwindow = gc.registerResource(vtkOpenGLRenderWindow.newInstance());
glwindow.setContainer(renderWindowContainer);
renderWindow.addView(glwindow);
glwindow.setSize(400, 400);

const gridSource = gc.registerResource(vtkImageGridSource.newInstance());
gridSource.setDataExtent(0, 200, 0, 200, 0, 0);
gridSource.setGridSpacing(16, 16, 0);
gridSource.setGridOrigin(8, 8, 0);
gridSource.setDataDirection(0.866, 0.5, 0, -0.5, 0.866, 0, 0, 0, 1);

const imapper = gc.registerResource(vtkImageMapper.newInstance());
imapper.setInputConnection(gridSource.getOutputPort());

const iactor = gc.registerResource(vtkImageSlice.newInstance());
iactor.getProperty().setColorWindow(255);
iactor.getProperty().setColorLevel(127);
iactor.setMapper(imapper);
iactor.setPosition(200, 100, 100);
iactor.rotateX(45);
renderer.addActor(iactor);

// Interactor
const interactor = vtkRenderWindowInteractor.newInstance();
interactor.setStillUpdateRate(0.01);
interactor.setView(glwindow);
interactor.initialize();
interactor.bindEvents(renderWindowContainer);

reader.setUrl(`${__BASE_PATH__}/Data/volume/LIDC2.vti`).then(() => {
reader.loadData().then(() => {
renderer.addVolume(volume);
renderer.resetCamera();
renderer.getActiveCamera().zoom(1.5);
renderer.getActiveCamera().elevation(70);
renderer.getActiveCamera().orthogonalizeViewUp();
renderer.getActiveCamera().azimuth(-20);
renderer.resetCameraClippingRange();

const image = glwindow.captureImage();
testUtils.compareImages(
image,
[baseline1],
'Rendering/OpenGL/VolumeMapper/testIntermixedImage',
t,
1.8,
gc.releaseResources
);
});
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions Sources/Rendering/OpenGL/glsl/vtkPolyDataFS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ uniform int PrimitiveIDOffset;
// handle coincident offsets
//VTK::Coincident::Dec

//VTK::ZBuffer::Dec

void main()
{
// VC position of this fragment. This should not branch/return/discard.
Expand Down
1 change: 1 addition & 0 deletions Sources/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import './Rendering/OpenGL/Texture/test/testCreateCubeFromRawTexture';
import './Rendering/OpenGL/VolumeMapper/test/testComposite';
import './Rendering/OpenGL/VolumeMapper/test/testComposite16Bit';
import './Rendering/OpenGL/VolumeMapper/test/testIntermixed';
import './Rendering/OpenGL/VolumeMapper/test/testIntermixedImage';
import './Rendering/OpenGL/VolumeMapper/test/testLighting';
import './Testing/testAlgorithm';
import './Testing/testMacro';
Expand Down

0 comments on commit 85622e1

Please sign in to comment.