From f3e89550058d9f29bf011163033844d0bb6d9643 Mon Sep 17 00:00:00 2001
From: Joachim Pouderoux <joachim.pouderoux@perception4d.com>
Date: Tue, 14 Jun 2022 13:09:05 +1100
Subject: [PATCH] Allow the shader code to set the point size

---
 Rendering/OpenGL2/Testing/Cxx/CMakeLists.txt  |  1 +
 .../Testing/Cxx/TestProgramPointSize.cxx      | 77 +++++++++++++++++++
 .../Baseline/TestProgramPointSize.png.sha512  |  1 +
 Rendering/OpenGL2/vtkOpenGLPolyDataMapper.cxx | 17 ++++
 Rendering/OpenGL2/vtkOpenGLPolyDataMapper.h   | 13 ++++
 5 files changed, 109 insertions(+)
 create mode 100644 Rendering/OpenGL2/Testing/Cxx/TestProgramPointSize.cxx
 create mode 100644 Rendering/OpenGL2/Testing/Data/Baseline/TestProgramPointSize.png.sha512

diff --git a/Rendering/OpenGL2/Testing/Cxx/CMakeLists.txt b/Rendering/OpenGL2/Testing/Cxx/CMakeLists.txt
index 6ea5bdf60b8..db4d6511634 100644
--- a/Rendering/OpenGL2/Testing/Cxx/CMakeLists.txt
+++ b/Rendering/OpenGL2/Testing/Cxx/CMakeLists.txt
@@ -71,6 +71,7 @@ vtk_add_test_cxx(vtkRenderingOpenGL2CxxTests tests
   TestPointGaussianMapper.cxx
   TestPointGaussianMapperOpacity.cxx
   TestPointGaussianSelection.cxx,NO_DATA
+  TestProgramPointSize.cxx
   TestPropPicker2Renderers.cxx,NO_DATA
   TestRemoveActorNonCurrentContext.cxx
   TestRenderToImage.cxx
diff --git a/Rendering/OpenGL2/Testing/Cxx/TestProgramPointSize.cxx b/Rendering/OpenGL2/Testing/Cxx/TestProgramPointSize.cxx
new file mode 100644
index 00000000000..eb7d1b2cfe1
--- /dev/null
+++ b/Rendering/OpenGL2/Testing/Cxx/TestProgramPointSize.cxx
@@ -0,0 +1,77 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#include "vtkActor.h"
+#include "vtkCamera.h"
+#include "vtkNew.h"
+#include "vtkOpenGLPolyDataMapper.h"
+#include "vtkOpenGLRenderWindow.h"
+#include "vtkProperty.h"
+#include "vtkRegressionTestImage.h"
+#include "vtkRenderer.h"
+#include "vtkShaderProperty.h"
+#include "vtkSphereSource.h"
+#include "vtkTestUtilities.h"
+
+#include "vtkRenderWindowInteractor.h"
+
+#include "vtkOpenGLRenderWindow.h"
+
+//------------------------------------------------------------------------------
+int TestProgramPointSize(int argc, char* argv[])
+{
+  vtkNew<vtkRenderer> renderer;
+  renderer->SetBackground(0.0, 0.0, 0.0);
+  vtkNew<vtkRenderWindow> renderWindow;
+  renderWindow->SetSize(300, 300);
+  renderWindow->AddRenderer(renderer);
+  vtkNew<vtkRenderWindowInteractor> iren;
+  iren->SetRenderWindow(renderWindow);
+
+  vtkNew<vtkSphereSource> sphere;
+  sphere->SetThetaResolution(16);
+  sphere->SetPhiResolution(16);
+
+  vtkNew<vtkOpenGLPolyDataMapper> mapper;
+  mapper->SetInputConnection(sphere->GetOutputPort());
+  mapper->UseProgramPointSizeOn();
+  vtkNew<vtkActor> actor;
+  renderer->AddActor(actor);
+  actor->SetMapper(mapper);
+  actor->GetProperty()->SetRepresentationToPoints();
+
+  vtkShaderProperty* sp = actor->GetShaderProperty();
+  sp->AddVertexShaderReplacement("//VTK::ValuePass::Impl", // replace the normal block
+    true,                                                  // before the standard replacements
+    "gl_PointSize = (1.0 - gl_Position.z) * 8.0;\n"
+    "///VTK::ValuePass::Impl\n", // we still want the default
+    false                        // only do it once
+  );
+
+  renderWindow->SetMultiSamples(0);
+  renderer->ResetCamera();
+  renderer->GetActiveCamera()->Elevation(-45);
+  renderer->GetActiveCamera()->OrthogonalizeViewUp();
+  renderer->GetActiveCamera()->Zoom(1.5);
+  renderer->ResetCameraClippingRange();
+  renderWindow->Render();
+
+  int retVal = vtkRegressionTestImageThreshold(renderWindow, 0.5);
+  if (retVal == vtkRegressionTester::DO_INTERACTOR)
+  {
+    iren->Start();
+  }
+
+  return !retVal;
+}
diff --git a/Rendering/OpenGL2/Testing/Data/Baseline/TestProgramPointSize.png.sha512 b/Rendering/OpenGL2/Testing/Data/Baseline/TestProgramPointSize.png.sha512
new file mode 100644
index 00000000000..7cd47225f6c
--- /dev/null
+++ b/Rendering/OpenGL2/Testing/Data/Baseline/TestProgramPointSize.png.sha512
@@ -0,0 +1 @@
+21903f28c760e11b3775bb702a9ceb46f50a76c84520bfed90394eb1c3bca0d62cc5928801d874a29c243d7adca5042423a355b5bc7bfbb17a81372e374dc220
diff --git a/Rendering/OpenGL2/vtkOpenGLPolyDataMapper.cxx b/Rendering/OpenGL2/vtkOpenGLPolyDataMapper.cxx
index bbe25ee4eeb..0370fd64f79 100644
--- a/Rendering/OpenGL2/vtkOpenGLPolyDataMapper.cxx
+++ b/Rendering/OpenGL2/vtkOpenGLPolyDataMapper.cxx
@@ -96,6 +96,7 @@ vtkOpenGLPolyDataMapper::vtkOpenGLPolyDataMapper()
   this->DrawingVertices = false;
   this->ForceTextureCoordinates = false;
   this->SelectionType = VTK_POINTS;
+  this->UseProgramPointSize = false;
 
   this->PrimitiveIDOffset = 0;
   this->ShiftScaleMethod = vtkOpenGLVertexBufferObject::AUTO_SHIFT_SCALE;
@@ -3287,6 +3288,13 @@ void vtkOpenGLPolyDataMapper::RenderPieceStart(vtkRenderer* ren, vtkActor* actor
   vtkOpenGLState* ostate = renWin->GetState();
   ostate->vtkglPointSize(actor->GetProperty()->GetPointSize());
 
+#ifdef GL_PROGRAM_POINT_SIZE
+  if (this->UseProgramPointSize)
+  {
+    ostate->vtkglEnable(GL_PROGRAM_POINT_SIZE);
+  }
+#endif
+
   // timer calls take time, for lots of "small" actors
   // the timer can be a big hit. So we only update
   // once per million cells or every 100 renders
@@ -3434,6 +3442,15 @@ void vtkOpenGLPolyDataMapper::RenderPieceDraw(vtkRenderer* ren, vtkActor* actor)
 //------------------------------------------------------------------------------
 void vtkOpenGLPolyDataMapper::RenderPieceFinish(vtkRenderer* ren, vtkActor*)
 {
+#ifdef GL_PROGRAM_POINT_SIZE
+  if (this->UseProgramPointSize)
+  {
+    vtkOpenGLRenderWindow* renWin = static_cast<vtkOpenGLRenderWindow*>(ren->GetRenderWindow());
+    vtkOpenGLState* ostate = renWin->GetState();
+    ostate->vtkglDisable(GL_PROGRAM_POINT_SIZE);
+  }
+#endif
+
   vtkHardwareSelector* selector = ren->GetSelector();
   // render points for point picking in a special way
   if (selector && selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS)
diff --git a/Rendering/OpenGL2/vtkOpenGLPolyDataMapper.h b/Rendering/OpenGL2/vtkOpenGLPolyDataMapper.h
index d6a37e8e875..c4e76e1a11a 100644
--- a/Rendering/OpenGL2/vtkOpenGLPolyDataMapper.h
+++ b/Rendering/OpenGL2/vtkOpenGLPolyDataMapper.h
@@ -162,6 +162,18 @@ public:
   vtkGetMacro(PauseShiftScale, bool);
   vtkBooleanMacro(PauseShiftScale, bool);
 
+  /**
+   * Allow the shader code to set the point size (with gl_PointSize variable)
+   * instead of using the one defined by the property. Note that this flag is
+   * not available on OpenGLES as the feature is enabled by default. With
+   * OpenGL, the feature is turned off by default.
+   * Warning: on MacOS, enabling the feature result in non point drawing
+   * if the shaders do not set the point size.
+   */
+  vtkGetMacro(UseProgramPointSize, bool);
+  vtkSetMacro(UseProgramPointSize, bool);
+  vtkBooleanMacro(UseProgramPointSize, bool);
+
   enum PrimitiveTypes
   {
     PrimitiveStart = 0,
@@ -440,6 +452,7 @@ protected:
   vtkNew<vtkMatrix4x4> VBOShiftScale;
   int ShiftScaleMethod; // for points
   bool PauseShiftScale;
+  bool UseProgramPointSize;
 
   // if set to true, tcoords will be passed to the
   // VBO even if the mapper knows of no texture maps
-- 
GitLab