<div dir="ltr"><div><div><div><div><div>I've now realized that I've made a blunder. In order to get the two volumes to look the same, I should of course set the ScalarOpacityUnitDistance to the *same* value for both volumes.<br><br></div>The attached PNG shows the result when I set the ScalarOpacityUnitDistance to 0.006 (the spacing of the higher-resolution volume) for both volumes (code below).<br><br></div>The volumes now look very similar opacity-wise, but they are still not quite equal. The (0-255) HSV values of the left/right volumes are (0, 95, 100) and (0, 93, 100), so the right one (the low res one) is still a little less opaque than the left one.<br><br></div><div>Anyone who can explain where this discrepancy comes from?<br><br></div><div>My question is really: How can two volumes with the exact same shape (a cube) and bounds in VTK world coordinates looks different opacity-wise, when they are rendered with the same opacity transfer function and have the same ScalarOpacityUnitDistance<span class=""> s</span>et?<br></div><div><br></div>Elvis<br><br><br></div>main.cpp:<br><br>#include <algorithm><br><br>#include <vtkCamera.h><br>#include <vtkColorTransferFunction.h><br>#include <vtkGPUVolumeRayCastMapper.h><br>#include <vtkImageData.h><br>#include <vtkImageInterpolator.h><br>#include <vtkImageResize.h><br>#include <vtkPiecewiseFunction.h><br>#include <vtkRenderer.h><br>#include <vtkRenderWindow.h><br>#include <vtkRenderWindowInteractor.h><br>#include <vtkSmartPointer.h><br>#include <vtkVolume.h><br>#include <vtkVolumeProperty.h><br><br>// Create a volume from the given image<br>vtkSmartPointer<vtkVolume> createVolume(vtkSmartPointer<vtkImageData> image) {<br>    auto color = vtkSmartPointer<vtkColorTransferFunction>::New();<br>    color->AddRGBPoint(0.0, 1.0, 0.0, 0.0);<br>    color->AddRGBPoint(1.0, 1.0, 0.0, 0.0);<br><br>    auto opacity = vtkSmartPointer<vtkPiecewiseFunction>::New();<br>    opacity->AddPoint(0.0, 0.1);<br>    opacity->AddPoint(1.0, 0.1);<br><br>    auto property = vtkSmartPointer<vtkVolumeProperty>::New();<br>    property->SetColor(color);<br>    property->SetScalarOpacity(opacity);<br>    property->SetInterpolationTypeToLinear();<br>    property->ShadeOff();<br>    property->SetScalarOpacityUnitDistance(0.006);<br><br>    auto mapper = vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();<br>    mapper->SetInputData(image);<br><br>    auto volume = vtkSmartPointer<vtkVolume>::New();<br>    volume->SetMapper(mapper);<br>    volume->SetProperty(property);<br><br>    return volume;<br>}<br><br>int main(int argc, char *argv[]) {<br><br>    // Create a 30x30x30 volume<br>    auto image = vtkSmartPointer<vtkImageData>::New();<br>    image->SetDimensions(30, 30, 30);<br>    image->SetSpacing(0.006, 0.006, 0.006);<br>    image->AllocateScalars(VTK_FLOAT, 1);<br><br>    auto imagePtr = static_cast<float *>(image->GetScalarPointer());<br>    std::fill_n(imagePtr, 30 * 30 * 30, 1.0);<br><br>    auto volume = createVolume(image);<br><br>    // Create a smaller (10x10x10) version<br>    auto interpolator = vtkSmartPointer<vtkImageInterpolator>::New();<br>    interpolator->SetInterpolationModeToLinear();<br><br>    auto resize = vtkSmartPointer<vtkImageResize>::New();<br>    resize->SetInputData(image);<br>    resize->SetOutputDimensions(10, 10, 10);<br>    resize->SetInterpolator(interpolator);<br>    resize->Update();<br><br>    auto smallVolume = createVolume(resize->GetOutput());<br>    smallVolume->SetPosition(0.2, 0, 0);<br><br>    // Render the two volumes<br>    auto renderer = vtkSmartPointer<vtkRenderer>::New();<br>    renderer->SetBackground(1.0, 1.0, 1.0);<br>    renderer->AddVolume(volume);<br>    renderer->AddVolume(smallVolume);<br>    renderer->ResetCamera();<br><br>    auto camera = renderer->GetActiveCamera();<br>    camera->SetParallelProjection(1);<br><br>    auto window = vtkSmartPointer<vtkRenderWindow>::New();<br>    window->AddRenderer(renderer);<br>    window->SetSize(800, 400);<br><br>    auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();<br>    interactor->SetRenderWindow(window);<br>    interactor->Start();<br><br>    return 0;<br>}<br><br><br></div>CMakeLists.txt:<br><br>cmake_minimum_required(VERSION 3.1)<br> <br>project(TestCase)<br> <br>set(CMAKE_CXX_STANDARD 11)<br>set(CMAKE_CXX_STANDARD_REQUIRED ON)<br><br>find_package(VTK COMPONENTS<br>    vtkCommonCore<br>    vtkCommonDataModel<br>    vtkCommonExecutionModel<br>        vtkInteractionStyle<br>    vtkImagingCore<br>    vtkRenderingCore<br>    vtkRenderingOpenGL2<br>    vtkRenderingVolume<br>    vtkRenderingVolumeOpenGL2<br>)<br><br>add_executable(TestCase main.cpp)<br> <br>target_link_libraries(TestCase PUBLIC<br>    vtkCommonCore<br>    vtkCommonDataModel<br>    vtkCommonExecutionModel<br>    vtkImagingCore<br>        vtkInteractionStyle<br>    vtkRenderingCore<br>    vtkRenderingOpenGL2<br>    vtkRenderingVolume<br>    vtkRenderingVolumeOpenGL2<br>)<br><br>target_include_directories(TestCase PUBLIC<br>    ${VTK_INCLUDE_DIRS}<br>)<br><br><br>target_compile_definitions(TestCase PUBLIC<br>    ${VTK_DEFINITIONS}<br>)<br><div><div><div><div><div><div><div><div class="gmail_extra"><br><div class="gmail_quote">2017-02-09 14:45 GMT+01:00 Elvis Stansvik <span dir="ltr"><<a href="mailto:elvis.stansvik@orexplore.com" target="_blank">elvis.stansvik@orexplore.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div><div><div><div>Hi all,<br><br>The following example shows a 30x30x30 volume rendered, and next to it a downscaled version of it (but using an identical opacity/transfer function). Notice how in the result (attached), the downscaled version is less opaque. This is despite me using<br><br>    SetScalarOpacityUnitDistance(<wbr>image->GetSpacing()[0])<br><br></div>to set the scalar opacity unit distance to the spacing of the respective image. I would thought calling SetScalarOpacityUnitDistance like this would ensure both volumes look the same (apart from resolution).<br><br></div>How can I make both volumes look the same opacity-wise when using the same transfer functions?<br><br></div>Thanks in advance,<br></div>Elvis<br><br></div>main.cpp:<br><br><br>#include <algorithm><br><br>#include <vtkCamera.h><br>#include <vtkColorTransferFunction.h><br>#include <vtkGPUVolumeRayCastMapper.h><br>#include <vtkImageData.h><br>#include <vtkImageResize.h><br>#include <vtkPiecewiseFunction.h><br>#include <vtkRenderer.h><br>#include <vtkRenderWindow.h><br>#include <vtkRenderWindowInteractor.h><br>#include <vtkSmartPointer.h><br>#include <vtkVolume.h><br>#include <vtkVolumeProperty.h><br><br>// Create a volume from the given image<br>vtkSmartPointer<vtkVolume> createVolume(vtkSmartPointer<<wbr>vtkImageData> image) {<br>    auto color = vtkSmartPointer<<wbr>vtkColorTransferFunction>::<wbr>New();<br>    color->AddRGBPoint(0.0, 1.0, 0.0, 0.0);<br>    color->AddRGBPoint(1.0, 1.0, 0.0, 0.0);<br><br>    auto opacity = vtkSmartPointer<<wbr>vtkPiecewiseFunction>::New();<br>    opacity->AddPoint(0.0, 0.1);<br>    opacity->AddPoint(1.0, 0.1);<br><br>    auto property = vtkSmartPointer<<wbr>vtkVolumeProperty>::New();<br>    property->SetColor(color);<br>    property->SetScalarOpacity(<wbr>opacity);<br>    property-><wbr>SetInterpolationTypeToLinear()<wbr>;<br>    property->ShadeOff();<br>    property-><wbr>SetScalarOpacityUnitDistance(<wbr>image->GetSpacing()[0]);<br><br>    auto mapper = vtkSmartPointer<<wbr>vtkGPUVolumeRayCastMapper>::<wbr>New();<br>    mapper->SetInputData(image);<br><br>    auto volume = vtkSmartPointer<vtkVolume>::<wbr>New();<br>    volume->SetMapper(mapper);<br>    volume->SetProperty(property);<br><br>    return volume;<br>}<br><br>int main(int argc, char *argv[]) {<br><br>    // Create a 30x30x30 volume<br>    auto image = vtkSmartPointer<vtkImageData>:<wbr>:New();<br>    image->SetDimensions(30, 30, 30);<br>    image->SetSpacing(0.006, 0.006, 0.006);<br>    image->AllocateScalars(VTK_<wbr>FLOAT, 1);<br><br>    auto imagePtr = static_cast<float *>(image->GetScalarPointer());<br>    std::fill_n(imagePtr, 30 * 30 * 30, 1.0);<br><br>    auto volume = createVolume(image);<br><br>    // Create a smaller (10x10x10) version<br>    auto resize = vtkSmartPointer<<wbr>vtkImageResize>::New();<br>    resize->SetInputData(image);<br>    resize->SetOutputDimensions(<wbr>10, 10, 10);<br>    resize->Update();<br><br>    auto smallVolume = createVolume(resize-><wbr>GetOutput());<br>    smallVolume->SetPosition(0.2, 0, 0);<br><br>    // Render the two volumes<br>    auto renderer = vtkSmartPointer<vtkRenderer>::<wbr>New();<br>    renderer->SetBackground(1.0, 1.0, 1.0);<br>    renderer->AddVolume(volume);<br>    renderer->AddVolume(<wbr>smallVolume);<br>    renderer->ResetCamera();<br><br>    auto camera = renderer->GetActiveCamera();<br>    camera->SetParallelProjection(<wbr>1);<br><br>    auto window = vtkSmartPointer<<wbr>vtkRenderWindow>::New();<br>    window->AddRenderer(renderer);<br>    window->SetSize(800, 400);<br><br>    auto interactor = vtkSmartPointer<<wbr>vtkRenderWindowInteractor>::<wbr>New();<br>    interactor->SetRenderWindow(<wbr>window);<br>    interactor->Start();<br><br>    return 0;<br>}<br><br><br></div>CMakeLists.txt:<br><br><br>cmake_minimum_required(VERSION 3.1)<br> <br>project(TestCase)<br> <br>set(CMAKE_CXX_STANDARD 11)<br>set(CMAKE_CXX_STANDARD_<wbr>REQUIRED ON)<br><br>find_package(VTK COMPONENTS<br>    vtkCommonCore<br>    vtkCommonDataModel<br>    vtkCommonExecutionModel<br>    vtkInteractionStyle<br>    vtkImagingCore<br>    vtkRenderingCore<br>    vtkRenderingOpenGL2<br>    vtkRenderingVolume<br>    vtkRenderingVolumeOpenGL2<br>)<br><br>add_executable(TestCase main.cpp)<br> <br>target_link_libraries(TestCase PUBLIC<br>    vtkCommonCore<br>    vtkCommonDataModel<br>    vtkCommonExecutionModel<br>    vtkImagingCore<br>    vtkInteractionStyle<br>    vtkRenderingCore<br>    vtkRenderingOpenGL2<br>    vtkRenderingVolume<br>    vtkRenderingVolumeOpenGL2<br>)<br><br>target_include_directories(<wbr>TestCase PUBLIC<br>    ${VTK_INCLUDE_DIRS}<br>)<br><br><br>target_compile_definitions(<wbr>TestCase PUBLIC<br>    ${VTK_DEFINITIONS}<br>)<br></div>
</blockquote></div><br></div></div></div></div></div></div></div></div></div>