surface rendering artifacts

I am working on transitioning legacy VTK code (5.6) to 9.1+ and am encountering rendering
artifacts when visualizing a triangulated, mostly flat, 3D surface. The artifact does not occur with
our legacy code but does with builds against VTK tags v9.1.0 and v9.2.0.rc1.
A very basic pipeline with mostly defaults (ie., lighting etc.) but with customize camera parameters
produces the artifact shown below. C++ code is provided. Any suggestions on mitigating or eliminating
this artifact ?

A close up view of a corner of the planar surface:

Overview of the planar surface in wireframe:

Source:

// plane_artifact_vtk.cpp : A demonstration of polydata rendering artifact not present
// in vtk 5.6 (post introduction of shader support in vtk)
//

#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkPolyDataReader.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>

using namespace std;

int main(int argc, char* argv[])
{
	if (2 != argc)
	{
		std::cout << "Usage: plane_artifact_vtk <filename.vtp>" << std::endl;
		return EXIT_SUCCESS;
	}
	std::string filename(argv[1]);

	vtkNew<vtkRenderer> renderer;
	vtkNew<vtkCamera> camera;

	renderer->SetActiveCamera(camera);
	renderer->SetBackground(1, 1, 1);

	vtkNew<vtkRenderWindow> renderWindow;
	renderWindow->AddRenderer(renderer);
	renderWindow->SetSize(800, 800);
	renderWindow->SetWindowName("Plane Artifact VTK");

	vtkNew<vtkRenderWindowInteractor> interactor;
	interactor->SetRenderWindow(renderWindow);
	
	vtkNew<vtkInteractorStyleTrackballCamera> style;
	interactor->SetInteractorStyle(style);

	vtkNew<vtkPolyDataReader> reader;
	reader->SetFileName(filename.c_str());
	reader->Update();

	vtkNew<vtkPolyDataMapper> mapper;
	mapper->SetInputConnection(reader->GetOutputPort());

	vtkNew<vtkActor> actor;
	actor->SetMapper(mapper);
	renderer->AddViewProp(actor);

	double m_fAzimuth = 535;
	double m_fDip = 271;
	bool m_bParallelProjection = true;

	double m_fEast_Offset  = -2076927.0490000001;
	double m_fNorth_Offset = -14599585.767999999;
	double m_fDepth_Offset = -6113.5580000000000;
	double m_fDistance     = 40003208.092430003;
	double m_fZoomFactor   = 6499379.5999999996;
	int m_nZCoordScale     = 1;

	// set view up and direction of projection based on document settings
	double fAzim = m_fAzimuth / 720.0 * vtkMath::Pi();
	double fDip = m_fDip / 720.0 * vtkMath::Pi();
	double viewUp[3];

	viewUp[2] = cos(fDip);
	viewUp[0] = sin(fDip) * sin(fAzim);
	viewUp[1] = sin(fDip) * cos(fAzim);

	double focalPoint[3];
	// set focal point according to offsets 
	focalPoint[0] = -m_fEast_Offset;;
	focalPoint[1] = -m_fNorth_Offset;
	focalPoint[2] = m_fDepth_Offset * m_nZCoordScale;

	double directionOfProjection[3];
	directionOfProjection[2] = -sin(fDip);
	directionOfProjection[0] = cos(fDip) * sin(fAzim);
	directionOfProjection[1] = cos(fDip) * cos(fAzim);

	double position[3];
	position[0] = focalPoint[0] - directionOfProjection[0] * m_fDistance;
	position[1] = focalPoint[1] - directionOfProjection[1] * m_fDistance;
	position[2] = focalPoint[2] - directionOfProjection[2] * m_fDistance;

	double viewAngle = 180.0 / vtkMath::Pi() * 0.1 * 6400.0 / m_fZoomFactor;
	double m_fParallelScale = 325 * m_fDistance / m_fZoomFactor;

	std::cout << "parallel scale: " << m_fParallelScale << std::endl;
	std::cout << "      distance: " << m_fDistance << std::endl;
	std::cout << "   zoom factor: " << m_fZoomFactor << std::endl;
	std::cout << "   east offset: " << m_fEast_Offset << std::endl;
	std::cout << "  north offset: " << m_fNorth_Offset << std::endl;
	std::cout << "  depth offset: " << m_fDepth_Offset << std::endl;
	std::cout << "       azimuth: " << m_fAzimuth << std::endl;
	std::cout << "           dip: " << m_fDip << std::endl;

	camera->SetViewUp(viewUp);
	camera->SetPosition(position);
	camera->SetFocalPoint(focalPoint);
	camera->SetViewAngle(viewAngle);
	camera->SetParallelProjection(m_bParallelProjection);
	camera->SetParallelScale(m_fParallelScale);
	camera->SetClippingRange(m_fDistance / 5, m_fDistance * 5);

	interactor->Start();

   	return EXIT_SUCCESS;
}

I discovered by inserting vtkPolyDataNormals between reader and mapper the artifact is eliminated.
Another solution is to force the renderer to call ResetCamera() (eg., ‘r’ or 'R" key press) which
adjusts/resets the camera clipping range and parallel scale based on visible prop bounds. If
anyone has some insight as to why the artifact occurs post vtk 5.6 please comment.

have you tried with .GetProperty().SetInterpolationToFlat()

Hi Marco,

if I set the actor interpolation to flat, then my fix with poly data normals
no longer works … so does not resolve the issue. So far, the only fix that works directly
is polydata normals and indirectly regardless of interpolation mode is forcing reset camera clipping range.