Boundary of glyph2D appears white when overlay on darker color contour

Hello,

I am using vtkGlyph2D to plot a vector field (e.g., vtkExample: VectorField) and using vtkImageMapToColors to plot color contour of a scalar field (e.g., vtkExample: ImageMapToColors). I put the actor for the vector field and actor for the color contour in the same renderer to create a 2D plot that has the vector field overlay on the color contour. However, I observed that when the vectors are over darker contour colors, they have white outline surrounding them. Please see the image below.

Image after zoom-in:

I set the diffusive and specular parameters both to zero in the vector actor, but it didn’t work. So it is not the lighting issue. I used different colors for the color contour other than the grayscale color in the figure above. The white outline still exists. I set the vectors to colors other than black. The white outline still exists.

Please advise on how to get rid of the white outlines. Thanks so much in advance!

Below please see the code:

#include <iostream>
#include <sstream>
#include <tuple>
#include <vtkArrowSource.h>
#include <vtkCamera.h>
#include <vtkDoubleArray.h>
#include <vtkExtractVectorComponents.h>
#include <vtkGlyph2D.h>
#include <vtkImageActor.h>
#include <vtkImageData.h>
#include <vtkImageMapToColors.h>
#include <vtkImageMapper.h>
#include <vtkImageSlice.h>
#include <vtkImageSliceMapper.h>
#include <vtkInteractorStyleImage.h>
#include <vtkLookupTable.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPointData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkTextProperty.h>
#include <vtkUnsignedCharArray.h>



int main(int, char*[])
{

  // Define vector field parameters
  double Nx = 20;
  double Ny = 20;
  double Nt = Nx * Ny;
  double x_st = -400;
  double y_st = -400;
  double dx = 40;
  double dy = 40;
  double ratio_aspect = dx / dy;
  double center_x = Nx * dx / 2;
  double center_y = Ny * dy / 2;
  double velo_ratio = 0.005;
  double x_ed = x_st + (Nx - 1) * dx;
  double y_ed = y_st + (Ny - 1) * dy;

  vtkNew<vtkNamedColors> colors;

  vtkColor3d backgroundColor = colors->GetColor3d("White");

  // Create image data. "image" for vector field, "image1" for color contour
  vtkNew<vtkImageData> image;
  vtkNew<vtkImageData> image1;
  // Specify the size of the image data.
  image->SetDimensions(Nx, Ny, 1);
  image->SetSpacing(ratio_aspect, 1.0, 1.0);
  image->SetOrigin(0, 0, 0);

  image1->SetDimensions(Nx, Ny, 1);
  image1->AllocateScalars(VTK_FLOAT, 1);
  image1->SetSpacing(ratio_aspect, 1.0, 1.0);
  image1->SetOrigin(0, 0, 0);

  //fill data to image data
  int* dims = image->GetDimensions();

  double dist, velo, x_phy, y_phy;

  vtkSmartPointer<vtkDoubleArray> u = vtkSmartPointer<vtkDoubleArray>::New();
  u->SetName("u");
  u->SetNumberOfComponents(3);
  u->SetNumberOfTuples(Nt);

  for (auto z = 0; z < dims[2]; ++z)
  {
    for (auto y = 0; y < dims[1]; ++y)
    {
      for (auto x = 0; x < dims[0]; ++x)
      {
        
        int idx = z * Nt + y * Nx + x;
        x_phy = x * dx - center_x;
        y_phy = y * dy - center_y;
        dist = sqrt(x_phy * x_phy + y_phy * y_phy);
        velo = dist * velo_ratio;
        
        auto pixel = static_cast<float*>(image1->GetScalarPointer(x, y, z));
        if (abs(dist) < 1e-5)
        {
          pixel[0] = 0.0;
          u->SetTuple3(idx, 0.0, 0.0, 0.0);
        }
        else
        {
          pixel[0] = y_phy / dist * velo;
          u->SetTuple3(idx, y_phy / dist * velo, -x_phy / dist * velo, 0.0);
        }
      }
    }
  }
  image->GetPointData()->SetVectors(u);

  // Setup the arrows
  vtkNew<vtkArrowSource> arrowSource;
  arrowSource->Update();
  vtkNew<vtkGlyph2D> glyphFilter;
  glyphFilter->SetSourceConnection(arrowSource->GetOutputPort());
  glyphFilter->OrientOn();
  glyphFilter->SetScaleModeToScaleByVector();
  glyphFilter->ScalingOn();
  glyphFilter->SetVectorModeToUseVector();
  glyphFilter->SetInputData(image);
  glyphFilter->Update();

  // color
  // Map the scalar values in the image to colors with a lookup table:
  vtkNew<vtkLookupTable> lookupTable;
  lookupTable->SetHueRange(0, 0);
  lookupTable->SetSaturationRange(0, 0);
  lookupTable->SetValueRange(0.2, 1.0);
  lookupTable->SetNumberOfColors(256);
  lookupTable->SetHueRange(0.0, 0.667);
  lookupTable->SetRange(image1->GetScalarRange());
  lookupTable->Build();

  // Pass the original image and the lookup table to a filter to create
  // a color image:
  vtkNew<vtkImageMapToColors> scalarValuesToColors;
  scalarValuesToColors->SetLookupTable(lookupTable);
  scalarValuesToColors->PassAlphaToOutputOn();
  scalarValuesToColors->SetInputData(image1);
  scalarValuesToColors->Update();

  // Create color contour actor.
  vtkNew<vtkImageActor> imageActor;
  imageActor->GetMapper()->SetInputConnection(scalarValuesToColors->GetOutputPort());

  // vector actor
  vtkNew<vtkPolyDataMapper> vectorMapper;
  vectorMapper->SetInputConnection(glyphFilter->GetOutputPort());
  vtkNew<vtkActor> vectorActor;
  vectorActor->SetMapper(vectorMapper);
  vectorActor->GetProperty()->SetColor(colors->GetColor3d("Black").GetData());

  // Setup renderer.
  vtkNew<vtkRenderer> renderer;
  renderer->AddViewProp(vectorActor);
  renderer->AddActor(imageActor);
  renderer->ResetCamera();
  renderer->SetBackground(backgroundColor.GetData());
  renderer->SetBackground(colors->GetColor3d("SlateGray").GetData());

  // Setup render window.
  vtkNew<vtkRenderWindow> renderWindow;
  renderer->GetActiveCamera()->ParallelProjectionOn();
  renderWindow->AddRenderer(renderer);
  renderWindow->SetWindowName("VectorField and color contour");
  // Setup render window interactor.
  vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
  vtkNew<vtkInteractorStyleImage> style;
  renderWindowInteractor->SetInteractorStyle(style);

  // Render and start interaction.
  renderWindow->SetSize(1000, 1000);

  renderWindowInteractor->SetRenderWindow(renderWindow);
  renderer->ResetCamera();
  
  renderWindow->Render();

  renderWindowInteractor->Initialize();

  renderWindowInteractor->Start();

  return EXIT_SUCCESS;
}

I just tried your code. I am using VTK 9.3.0 on Debian 12 with OpenGL

erver glx version string: 1.4
client glx version string: 1.4
GLX version: 1.4
OpenGL core profile version string: 4.6.0 NVIDIA 525.147.05
OpenGL core profile shading language version string: 4.60 NVIDIA
OpenGL version string: 4.6.0 NVIDIA 525.147.05
OpenGL shading language version string: 4.60 NVIDIA
OpenGL ES profile version string: OpenGL ES 3.2 NVIDIA 525.147.05
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
    GL_EXT_shader_group_vote, GL_EXT_shader_implicit_conversions, 

and my array never appear with white outline. Which platform and version are you using

I am using VTK 9.3.0, Windows 10, and Visual Studio 2019.

I figured out it is the background issue. I displayed a background (e.g., imageslice) with the same color of the vectors, then the outlines are gone. Basically, the outline color is the color of the background.

Thank you for the help!