OSPRay colouring materials by scalar

vtk
(Daan Van Vugt) #1

Hi,

I’m using VTK 8.2.0 and OSPRay 1.8.5 from python to show some particle traces (using the Tube filter).
I’m having trouble transferring my colour map to the ray tracer. The particle traces remain black.

Is there a way to transfer the colour properties from my cells to the material OSPRay will use to render?
Or must I have static material properties?

The suggestion by @Dave_DeMarle in How to set up material lookuptable for OSPRay also doesn’t work out for me yet, but might work since I have a discrete colourmap in mind.

Any input is welcome,

Thanks,
Daan

ps: I create a material lookup table (Value Indexed) as follows:

def W_lut(n_Z=74):
  import matplotlib
  import matplotlib.cm as cm

  lut = vtk.vtkLookupTable()
  lut.SetNumberOfTableValues(n_Z+1)
  lut.Build()

  norm = matplotlib.colors.Normalize(vmin=0,vmax=74,clip=True)
  mapper = cm.ScalarMappable(norm=norm, cmap=cm.inferno)
  ll = []

  for i, u in enumerate(range(75)):
    lut.SetTableValue(i, mapper.to_rgba(u))
    ll.append('W_%d'%(i,))

  lut.Annotations = ll
  lut.InterpretValuesAsCategories = 1

  return lut

and create the materials as:

# Add colormap variables (75 discrete levels)
import matplotlib
import matplotlib.cm as cm
norm = matplotlib.colors.Normalize(vmin=0,vmax=74,clip=True)
mapper = cm.ScalarMappable(norm=norm, cmap=cm.inferno)
for i, u in enumerate(range(75)):
  name = 'W_%d'%(i,)
  ml.AddMaterial(name, "Alloy")
  ml.AddShaderVariable(name, "color", 3, mapper.to_rgba(u)[0:3])
(Dave DeMarle) #2

Hi Daan.

A couple of thoughts.

1: you probably don’t need the tube filter. OSPRay will render streamlines directly as tubes. You can control the width of the tube via vtkProperty::LineWidth (constant width) or by applying a scaling array (width is a function of some scalar). See https://gitlab.kitware.com/vtk/vtk/blob/master/Rendering/RayTracing/Testing/Cxx/TestOSPRayImplicits.cxx

2: Do you need special materials (reflective/refractive/variable appearance)? If not the default OBJMaterial should do color mapping just like a normal VTK render will for any point or cell aligned array. See https://gitlab.kitware.com/vtk/vtk/blob/master/Rendering/RayTracing/Testing/Cxx/TestOSPRayRenderMesh.cxx and run it with the -type and -rep command line arguments to draw the spheres with lines instead of triangle/surfaces.

3: If you do need fancy materials and are aware of 2, then let me know and I’ll look harder at your script to try and see what is going wrong.

hth

(Daan Van Vugt) #3

Hi Dave,

Thanks for the quick suggestions. I think I’ll keep the tube filter since it looks better in the OpenGL renderer we use to setup the scenes.

I don’t need any special properties, this was all just trickery to try to get colours.
I’ve just tried with OBJMaterial, which comes out very white instead of coloured.
See the renders below:

the renderer is just setup as

if not self.ospray: self.ospray = vtk.vtkOSPRayPass()

self.parent.renderer.SetPass(self.ospray)
self.render_node.SetSamplesPerPixel(1, self.parent.renderer)
#self.render_node.SetAmbientSamples(1, self.parent.renderer)
self.render_node.SetRendererType(osp_renderer,self.parent.renderer)
self.parent.renderer.SetBackground(0.9, 0.9, 0.9) 
self.parent.renderer.SetBackground2(0.9, 0.9, 1.0)
(Dave DeMarle) #4

Can you share the parts of the code where you set up the mapper and lookup table? In particular, you shouldn’t need to set any material or special color map at all. The way it should work is that if the only thing you do is set the ospray pass, the vtk2ospray code c++ will internally make and setup an ospray::OBJMaterial such that color mapping will work and you will get an image that looks very similar to the gl rendered image you would have without OSPRay.

To demonstrate, open paraview, open the diskoutref.ex2 sample data set, apply streamlines and tube (optionally point to cell filter), color by some array, and turn on ospray.

(Daan Van Vugt) #5

Hi Dave,

This is how I create the dataset (particle positions at many times)

# n_p * n_t, 3
pcoords = npvtk.numpy_to_vtk(xyz[:,:,:].reshape(-1,3), deep=True, array_type=vtk.VTK_FLOAT)

self.points = vtk.vtkPoints()
self.points.SetData(pcoords)

# n_p * n_t
q = npvtk.numpy_to_vtk(np.asarray(self.particles.q[0:n_p,:]).ravel(), deep=True, array_type=vtk.VTK_FLOAT)
q.SetName('q')

vtk_points.poly = vtk.vtkPolyData()
vtk_points.poly.SetPoints(self.points)
vtk_points.poly.GetPointData().AddArray(q)
vtk_points.poly.GetPointData().SetActiveScalars('q')

# Set connectivity data per particle
lines = vtk.vtkCellArray()
# See https://vtk.org/Wiki/VTK/Examples/Python/GeometricObjects/Display/PolyLine
for i in range(n_p):
  lines.InsertNextCell(n_t, range(n_t*i, n_t*i+n_t))
vtk_points.poly.SetLines(lines)

vtk_points.lut = vtk_lut.W_lut() #as in first post on discourse

tube = vtk.vtkTubeFilter()
tube.SetInputData(vtk_points.poly)
tube.SetNumberOfSides(6)
tube.SetVaryRadiusToVaryRadiusOff()
tube.SetRadius(0.015)

vtk_points.mapper = vtk.vtkPolyDataMapper()
vtk_points.mapper.SetInputConnection(tube.GetOutputPort())
vtk_points.mapper.ScalarVisibilityOn()
vtk_points.mapper.SetScalarRange(vtk_points.poly.GetPointData().GetArray('q').GetRange())
vtk_points.mapper.SetLookupTable(vtk_points.lut)


vtk_points.actor = vtk.vtkActor() 
vtk_points.actor.SetMapper(vtk_points.mapper)
#vtk_points.actor.GetProperty().SetMaterialName("Value Indexed")
vtk_points.actor.GetProperty().SetMaterialName("OBJMaterial")

vtk_points.colorbar = vtk_color_bar()
vtk_points.colorbar.SetLookupTable(vtk_points.lut)
vtk_points.colorbar.SetTitle('q')
vtk_points.colorbar.SetPosition(0.05, 0.1)

return vtk_points
(Dave DeMarle) #6

Try commenting out this line

vtk_points.actor.GetProperty().SetMaterialName(“OBJMaterial”)

(Daan Van Vugt) #7

That gives me a very interesting picture, where the lines are black
and I guess there is no data on many of the points on the solid material below

(Dave DeMarle) #8

Try turning off the annotations and categorical nature of the color map please. Either should be OK I think but you could be exercising a code path/bug I haven’t seen yet.

Since the color is too dark it might be something odd like inverted normals on the tube filter but that seems unlikely. In general I find a good trick to debugging things is to insert writers into the code and open the output up in paraview to debug what you are looking at.

I’m stumped at the moment otherwise.

(Daan Van Vugt) #9

I’ve tried the annotations and categorical nature without any difference.
Saving the tubes with a vtkPDataSetWriter and opening in paraview 5.6.0 works,
and there I can OSPRay without any issue and get nice colours. We probably did something wrong in setting up the ray tracer (or in my own build of OSPRay and VTK 8.2.0).

I will try to get our stl files into paraview and render from there.