VTK produces aliased images when off-screen rendering is on. How do we get rid of it ?

Hi. I do not understand why VTK produces aliased images when rendering off screen. I have the following code

#include <vtkCamera.h>
#include <vtkConeSource.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkPolyDataMapper.h>
#include <vtkCamera.h>
#include <vtkOutlineFilter.h>
#include <vtkProperty.h>
#include <vtkPNGWriter.h>
#include <vtkWindowToImageFilter.h>


int main(int, char *[])
{
  //Create a cone
  vtkNew<vtkConeSource> cone;
  cone->SetHeight(300.0);
  cone->SetRadius(120.0);
  cone->SetResolution(10);

  // Create a new outline box for the data using the outline filter. It seems 
  // All filters require SetInputConnection for receiving data.  
  // SetInputConnection connects to the output port(pointer) to the data.
  
  vtkNew<vtkOutlineFilter> outlineFilter;
  outlineFilter->SetInputConnection(cone->GetOutputPort());

  // Set the properties of the outlining box

  vtkNew<vtkProperty> outlineProperty;
  outlineProperty->SetColor(0,0,0);
  outlineProperty->SetLineWidth(0.4);


  //Create mappers 
  vtkNew<vtkPolyDataMapper> coneMapper; 
  coneMapper->SetInputConnection(cone->GetOutputPort());

  vtkNew<vtkPolyDataMapper> outlineMapper;
  outlineMapper->SetInputConnection(outlineFilter->GetOutputPort());

  // Create actors for outline and cone

  vtkNew<vtkActor> outline;
  outline->SetMapper(outlineMapper);
  outline->SetProperty(outlineProperty);

  vtkNew<vtkActor> coneActor; 
  coneActor->SetMapper(coneMapper);

  //Create a renderer and add cone & outline to it.
  
  vtkNew<vtkRenderer> ren1;
  ren1->AddActor(coneActor);
  ren1->AddActor(outline);

  // Set background color of the renderer
  vtkNew<vtkNamedColors> colors;
  ren1->SetBackground(colors->GetColor3d("White").GetData()); 

  // Create a new visualization window and add the renderer to it.
  vtkNew<vtkRenderWindow> renWin;
  renWin->SetLineSmoothing(1);
  renWin->AddRenderer(ren1);
  renWin->SetOffScreenRendering(1);
  renWin->SetSize(600,600);

  // Create a virtual camera
  vtkNew<vtkCamera> orientation;
  orientation->SetFocalPoint(0,0,0);
  orientation->SetPosition(500,500,500);
  ren1->SetActiveCamera(orientation);

  // Make the render window interacting

  //vtkNew<vtkRenderWindowInteractor> renWinInteractor;
  //renWinInteractor->SetRenderWindow(renWin);

  
  //Render and interact
    renWin->Render();
  //  renWinInteractor->Start();

  //-------------------------------------------------------------------------------

  // Create a PNG image writer 

  vtkNew<vtkPNGWriter> pngWriter;

  // Create a filter from window to image

  vtkNew<vtkWindowToImageFilter> window_to_image_filter; 

  // Let the render window go through the filter

  window_to_image_filter->SetInput(renWin);
  window_to_image_filter->SetInputBufferTypeToRGB(); // record from the back buffer with RGB colors
  window_to_image_filter->ReadFrontBufferOff(); // read from back buffer (read about double buffering to understand font and back buffers)
  window_to_image_filter->Update();


  // Write to the file

  pngWriter->SetFileName("cone_aliased.png");
  pngWriter->SetInputConnection(window_to_image_filter->GetOutputPort());
  pngWriter->Write();
  
  return EXIT_SUCCESS;
}

The code above without window interactor creates the following aliased image,

If we turn the interactor on and switch off off-screen rendering, I get the following smooth anti-aliased image

I am wondering why this is happening ? Is this because I am not using OSMESA drivers ? In the VTK user guide, it is mentioned that Multisampling depends on OpenGL implementation. Is there anyway I can get rid of aliasing when rendering off screen (using GPU) ? I tried setting renWin->SetMultiSamples(8) as well, but that did not help.

Thank you and best regards.

Any solutions ? Thank you.

IIRC, we turn on some multisampling antialiasing by default for platform specific render targets, and this might not be happening on the offscreen renderers.

Try explicitly enabling it on the render window:

renWin->SetMultiSamples(8);

and see if that helps.

Allison, thank you for the response. I think I forgot to mention in my post that I did try setting renWin->SetMultiSamples(8) and it didn’t work. That is the main reason I posted the question here.

Hmm, maybe the gl implementation you’re using doesn’t support multisampling for offscreen targets. Did you try FXAA as well? That’s implemented in software so it should work everywhere.

Allison, thanks a lot. Setting ren1->UseFXAAOn() worked as far as anti-aliasing goes but for some reason the thickness of the outline is not controllable. Even in the pictures above, the outlines are of different thicknesses. I had earlier thought that this was due to aliasing. But even with FXAA on, the outline is too thick for my liking and it doesn’t change even if I change the value in the setting outlineProperty->SetLineWidth(0.1). I am basically getting the following image at this moment

Update: I tried changing the resolution of the image by setting renWin->SetSize(1200,1200). This made the image better and reduced the thickness, but it is confusing, since the second image in my original post (with nice anti-aliasing) was produced using 600x600 resolution. Why does the second image (anti-aliased) in my original post doesn’t match the off screen rendered image produced using FXAA on ?

Thanks again.

My guess is that the GL implementation is always drawing the line 1px wide, and then FXAA works by selectively blurring the line at the rough edges. This blurring is smearing the line out a bit, making it thicker. To get the same exact image, you’d need to use the same anti-aliasing method.

It seems strange that MSAA isn’t working for your offscreen targets, though. @ken-martin, do you have any idea why MSAA isn’t working here?

If I remember correctly, you can use glxinfo on linux to retrieve the valid framebuffer configurations for gl:

There’s a large table like this at the end:

76 GLX Visuals                                                                                                       
    visual  x   bf lv rg d st  colorbuffer  sr ax dp st accumbuffer  ms  cav                                          
  id dep cl sp  sz l  ci b ro  r  g  b  a F gb bf th cl  r  g  b  a ns b eat                                          
----------------------------------------------------------------------------                             

The ms column denotes multisampling support, but you’ll need to look up the rest and see if they make sense for your requested framebuffer.