vtkOpenGLGPUVolumeRayCastMapper crashes with more than 6 lights
Hi all,
I think there is a small issue in the concrete implementation vtkOpenGLGPUVolumeRayCastMapper. The stack is smashed when there are more than 6 lights in the scene. Below is a code to reproduce the crash :
#include <vtk-9.1/vtkNew.h>
#include <vtk-9.1/vtkSmartPointer.h>
#include <vtk-9.1/vtkImageData.h>
#include <vtk-9.1/vtkGPUVolumeRayCastMapper.h>
#include <vtk-9.1/vtkVolumeProperty.h>
#include <vtk-9.1/vtkRenderWindowInteractor.h>
#include <vtk-9.1/vtkRenderer.h>
#include <vtk-9.1/vtkRenderWindow.h>
#include <vtk-9.1/vtkPiecewiseFunction.h>
#include <vtk-9.1/vtkColorTransferFunction.h>
#include <vtk-9.1/vtkFloatArray.h>
#include <vtk-9.1/vtkPointData.h>
#include <vtk-9.1/vtkActor.h>
#include <vtk-9.1/vtkPoints.h>
#include <vtk-9.1/vtkCellArray.h>
#include <vtk-9.1/vtkVertex.h>
#include <vtk-9.1/vtkActor.h>
#include <vtk-9.1/vtkLight.h>
#include <vtk-9.1/vtkCamera.h>
#include <vtk-9.1/vtkProperty.h>
int main()
{
vtkNew<vtkImageData> imgdata;
imgdata->SetOrigin(0.0, 0.0, 0.0);
imgdata->SetDimensions(1, 1, 1);
vtkNew<vtkFloatArray> dataArray;
dataArray->SetNumberOfComponents(1);
dataArray->SetNumberOfTuples(1);
dataArray->SetTuple1(0, 0);
imgdata->GetPointData()->SetScalars(dataArray);
/* minimalist volume setup */
vtkNew<vtkRenderer> ren;
vtkNew<vtkRenderWindow> renwin;
renwin->AddRenderer(ren);
vtkNew<vtkRenderWindowInteractor> renint;
renint->SetRenderWindow(renwin);
vtkNew<vtkVolumeProperty> volumeProperty;
volumeProperty->ShadeOn();
vtkNew<vtkVolume> volume;
volume->SetProperty(volumeProperty);
vtkNew<vtkGPUVolumeRayCastMapper> mapper;
mapper->SetInputData(imgdata);
volume->SetMapper(mapper);
int nr_light = 8; // increase it above 6 to crash
ren->ClearLights();
ren->RemoveAllLights();
for(int i=0; i<nr_light; i++)
{
vtkNew<vtkLight> light;
light->SetPositional(true);
light->SetPosition(1.0, 1.0, 1.0);
light->SetFocalPoint(0.0, 0.0, 0.0);
light->SetConeAngle(45);
light->SetIntensity(1.0);
ren->AddLight(light);
}
ren->AddActor(volume);
renwin->Render();
renint->Start();
}
The reason for this is in vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::SetLightingShaderParameters
: we iterate over the lights with an array of an hard-coded size of 6, without doing additional checks, and it causes the crash. A simple fix would be to consider only the 6 first lights during the traversal, and show a warning for the user. A better solution would be to support an arbitrary number of light, but this 6 is also hard-coded in the ShaderComposer, so it would take more time to fix.
I'll open an MR for the first solution quickly.
edit : !9039 (merged)
Thanks ! Gaspard