Create a vtkTexture from in-memory imagedata

I am trying to create a vtkTexture for use on a Quad object. I have the data already existing in memory as an array of floating point values between about 0.3 and 0.93. I have created a vtkLookupTable to map from the values to a color. I am having trouble figuring out how to hook all of this up in a visualization pipeline. I have looked at examples but all of the examples have you loading an pre-existing image from the file system.

Thanks

The easiest way to do this is to create a vtkImageData object with the RGB colors as the active points array the set that as the input to the texture:

image = vtk.vtkImageData()

# `colors` is your vtk array of all the colors
image.GetPointData().AddArray(colors)

tex = vtk.vtkTexture()
tex.SetInputDataObject(image)
tex.Update()
# now the texture is ready for use
1 Like

Is there anything special that I need to do if I am just starting with an array of data? I would expect that i need to use a Lookup Table to generate the RGB colors and then plug those generated RGB colors into vtkImageObject and then the output from the vtkImageObject into the vtkTexture?

Once the texture is being displayed by OpenGL is there anything special that I need to do if the original source input data changes? Our input data changes and some where in the visualization pipeline the colors are just not getting updated in the render windows. I have stepped through the code and verified that new colors are being generated but the displayed image just does not want to update. We have called “update()” on just about everything we can think of. We even tried ripping out the vtkActor and instantiating a new one which oddly didn’t seem to help.

In simple terms this is the flow.

user selects a data set that we create a texture from using a vtkLookupTable. The original range of that data is 0 to 1 and we use a fairly standard blue (0) to red (1) color interpolation.

The use then selects a different data set where the range is now 0 to 100 (evenly distributed). When the new dataset is rendered we just get a solid red Quad rendered.

Clearly we are not setting something up correctly, just having a hard time trying to figure out what our bug is.

Thanks
M. Jackson

Calling Update() doesn’t force re-execution. It tells the pipeline to check the timestamps and re-execute if things are out of date. And Update() only causes VTK data pipeline stuff to update. It never causes OpenGL code to execute (so calling Update() will never directly cause a texture to be loaded onto the GPU).

The rule is: the texture will reload if the timestamp of the array that is used by the texture is modified and Render() is subsequently called on the RenderWindow (or on the Interactor, viewer, etc.).

Following Bane’s code example above, if you call colors.Modified(), the texture will reload on the next Render(). Calling texture.Update() just updates the upstream pipeline, it doesn’t cause anything to move onto the GPU.

Roughly,

  1. When a filter re-executes, the arrays in its output data are modified, so calling Modified() on a filter that is upstream of your texture should cause the texture to reload on the next render.
  2. You can also force a texture (or mapper) to re-execute on the next render by explicitly calling Modified() on the input data array before the render. Note that it is the data array, not the data object that must be modified.

Dear David,
Thanks for the tips but unfortunately I still cannot get my render to update to a new set of colors. I think our basic design is just incorrect and we are going to have to go back to the drawing board to get this figured out. I can post some code of the functions that we are using to update the texture if you think it might help.


Mike Jackson

Are you using Python? If so, try plugin PyVista into your workflow - PyVista has a few helper methods to handle making textures like pyvista.numpy_to_texture() and the pyvista.Texture class has a few different ways to create textures

Unfortunately I am not using python although it might be interesting to dig into those methods as the C++ analogs to them should be straight forward. I guess what I am really looking for is an example (in C++ preferably) that goes from a vtkDataArray of just floats that represent some data, through a look up table and into an actor, renderer, source, mapper and what ever else it takes.


Mike Jackson

All of my comments were regarding how to make the texture re-render. If the texture didn’t even render the first time, those comments were pretty much irrelevant.

Does the quad that you are texturing have texture coords? Texture coords are needed for any geometry you want to apply a texture to. The VTK geometry sources like vtkPlaneSource will automatically generate texture coords, but if you generate the geometry from scratch, you will either have to add the texture coords yourself, or generate them with a filter like vtkTextureMapToPlane.

Turns out we were missing something along the lines of this:

imageData->GetCellData()->SetActiveScalars(m_ActiveArrayName);

when we were updating the data to be visualized.

Are you sure it was the cell data scalars? As far as I understand, the texture is made from the point data scalars.