[vtkusers] vtkSmartVolumeMapper blending problems

Stephan Rademacher stephan.rademacher at iontof.com
Wed Dec 4 04:35:42 EST 2013


Dear all,

I have a problem with volume rendering on windows machines that have the 
Mobile Intel(R) 4 Series chipset (so no dedicated graphics card). I use 
VTK 5.10, 32bit.

I use vtkSmartVolumeMapper to allow switching between CPU and GPU 
raycasting on the fly. This usually works very well, but with the 
grapics chip mentioned above I get a black background after switching 
from GPU to CPU. This switch from GPU to CPU is important, if I only use 
CPU everything is fine. I attached three screenshots demonstrating the 
effect:

The first one is CPU (demonstrating that CPU alone works fine), the 
second is after the switch to GPU (which works fine), and the third is 
after the switch back to CPU. This is when the black background appears.

This effect does not happen on any NVIDIA cards I tested. I didn't test 
ATI because I don't have one. I debugged the issue and discovered that 
the problem seems to be in  vtkOpenGLRayCastImageDisplayHelper.cxx in 
the function RenderTextureInternal. This is the function the CPU 
raycaster uses to display the raycasted texture. There the blending 
function is set up (using glBlendFunc), but blending is never enabled 
(so glEnable(GL_BLEND) is not called).

This is no problem when only using CPU, because the 
vtkOpenGLRenderWindow enables blending in its OpenGLInitState method. 
But the GPU raycaster enables blending, renders, and then disables it 
again. So when switching back to CPU, blending is disabled, and 
vtkOpenGLRayCastImageDisplayHelper::RenderTextureInternal never enables 
it again, resulting in the black background.

I added a glEnable(GL_BLEND) in 
vtkOpenGLRayCastImageDisplayHelper::RenderTextureInternal right before 
glBlendFunc is called, and the problem goes away.

I'm not sure why NVIDIA cards (the ones I tested) don't show the black 
background, but I think this is a bug in VTK. Configuring OpenGL 
blending without enabling it seems wrong to me.

The problematic chipset is mostly in notebooks, so you might not be able 
to reproduce it on a desktop machine. Well, maybe the problem exists for 
all Intel drivers, I don't know. If you have a notebook with this 
chipset, it is important to disable any additional dedicated graphics 
card you might have, otherwise the effect might not occur. This is a 
small program that can be used to demonstrate the effect:

#include "vtkColorTransferFunction.h"
#include "vtkCommand.h"
#include "vtkPiecewiseFunction.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkSmartVolumeMapper.h"
#include "vtkStructuredPointsReader.h"
#include "vtkVolume.h"
#include "vtkVolumeProperty.h"
#include "vtkVolumeRayCastMapper.h"

class MyCallBack: public vtkCommand
{
public:

    static MyCallBack *New()
    {
        return new MyCallBack;
    }

    virtual void Execute(vtkObject* caller, unsigned long eventId, void* 
callData)
    {
        if (eventId == vtkCommand::KeyPressEvent)
        {
            if (smartMapper->GetRequestedRenderMode() == 
vtkSmartVolumeMapper::GPURenderMode)
            {
                
smartMapper->SetRequestedRenderMode(vtkSmartVolumeMapper::RayCastRenderMode); 

                std::cout << "Changed to CPU RayCasting" << std::endl;
            }
            else if (smartMapper->GetRequestedRenderMode() == 
vtkSmartVolumeMapper::RayCastRenderMode)
            {
                
smartMapper->SetRequestedRenderMode(vtkSmartVolumeMapper::GPURenderMode);
                std::cout << "Changed to GPU RayCasting" << std::endl;
            }
            renderWindow->Render();       
        }   
    }

    vtkSmartPointer<vtkSmartVolumeMapper> smartMapper;
    vtkSmartPointer<vtkRenderWindow> renderWindow;
};

int main()
{
    vtkSmartPointer<vtkStructuredPointsReader>    pointsReader = 
vtkSmartPointer<vtkStructuredPointsReader>::New();
    pointsReader->SetFileName("ironProt.vtk");

    vtkSmartPointer<vtkSmartVolumeMapper> smartVolumeMapper = 
vtkSmartPointer<vtkSmartVolumeMapper>::New();
    smartVolumeMapper->SetInputConnection(pointsReader->GetOutputPort() );
    smartVolumeMapper->SetRequestedRenderMode(vtkSmartVolumeMapper::RayCastRenderMode); 


    vtkSmartPointer<vtkColorTransferFunction> colorTransferFunction = 
vtkSmartPointer<vtkColorTransferFunction>::New();
    colorTransferFunction->AddRGBPoint(  0.0, 0.0, 0.0, 0.0);
    colorTransferFunction->AddRGBPoint( 64.0, 1.0, 0.0, 0.0);
    colorTransferFunction->AddRGBPoint(128.0, 0.0, 0.0, 1.0);
    colorTransferFunction->AddRGBPoint(192.0, 0.0, 1.0, 0.0);
    colorTransferFunction->AddRGBPoint(255.0, 0.0, 0.2, 0.0);

    vtkSmartPointer<vtkPiecewiseFunction> opacityTransferFunction = 
vtkSmartPointer<vtkPiecewiseFunction>::New();
    opacityTransferFunction->AddPoint(0, 0.0);
    opacityTransferFunction->AddPoint(255, 1.0);

    vtkSmartPointer<vtkVolumeProperty> volumeProperty = 
vtkSmartPointer<vtkVolumeProperty>::New();
    volumeProperty->SetColor(colorTransferFunction);
    volumeProperty->SetScalarOpacity(opacityTransferFunction);
    
    vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
    volume->SetMapper(smartVolumeMapper);
    volume->SetProperty(volumeProperty);
 
    vtkSmartPointer<vtkRenderer> renderer = 
vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(volume);
    renderer->SetBackground(1.0, 1.0, 1.0);

    vtkSmartPointer<vtkRenderWindow> renderWindow = 
vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->SetSize(800, 600);
    renderWindow->AddRenderer(renderer);

    vtkSmartPointer<vtkRenderWindowInteractor> interactor= 
vtkSmartPointer<vtkRenderWindowInteractor>::New();
    interactor->SetRenderWindow(renderWindow);
    vtkSmartPointer<MyCallBack> callback = 
vtkSmartPointer<MyCallBack>::New();
    callback->smartMapper    = smartVolumeMapper;
    callback->renderWindow    = renderWindow;
    interactor->AddObserver("KeyPressEvent", callback);

    renderWindow->Render();
    interactor->Start();
}


This program renders ironProt.vtk, initially using CPU raycasting. 
Pressing any key will toggle betweeln CPU raycasting and GPU raycasting.

Do you agree this is a bug, or am I doing something wrong? If I should 
have sent this to the developers list instead of the users list, I'm sorry.

Kind Regards,
Stephan Rademacher
-------------- next part --------------
A non-text attachment was scrubbed...
Name: rendering_1_cpu.png
Type: image/png
Size: 58231 bytes
Desc: not available
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20131204/509284db/attachment-0003.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: rendering_2_gpu.png
Type: image/png
Size: 58973 bytes
Desc: not available
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20131204/509284db/attachment-0004.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: rendering_3_cpu.png
Type: image/png
Size: 41075 bytes
Desc: not available
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20131204/509284db/attachment-0005.png>


More information about the vtkusers mailing list