Adding shader program to VTK OpenGL pipeline

I’m trying to use an OpenGL shader I have that renders an infinite regular grid for use as a reference in the visualization of a vehicle trajectory. I’ve confirmed it works in base OpenGL, but I’m a bit confused on how I would implement it in the current shader system in VTK. It seems there is no way to add additional shader programs to the pipeline directly but instead I have to add them as overrides to the shader templates that VTK uses. However, it’s not clear which parts of the templates I should override. Can anyone help provide guidance on this? The shaders are included below for reference.

fs.glsl

#version 450
in vec3 nearPoint; // nearPointPoint calculated in vertex shader
in vec3 farPoint;      // farPointPoint calculated in vertex shader

uniform mat4 view;
uniform mat4 proj;

out vec4 outColor;

float checkerboard(vec2 R, float scale) {
  return float((int(floor(R.x / scale)) + int(floor(R.y / scale))) % 2);
}

float computeDepth(vec3 pos) {
  vec4 clip_space_pos = proj * view * vec4(pos.xyz, 1.0);
  float clip_space_depth = clip_space_pos.z / clip_space_pos.w;

  float farPoint = gl_DepthRange.far;
  float nearPoint = gl_DepthRange.near;

  float depth =
      (((farPoint - nearPoint) * clip_space_depth) + nearPoint + farPoint) /
      2.0;

  return depth;
}

void main() {
  float t = -nearPoint.y / (farPoint.y - nearPoint.y);
  vec3 R = nearPoint + t * (farPoint - nearPoint);

  float c = checkerboard(R.xz, 1) * 0.3 + checkerboard(R.xz, 10) * 0.2 +
            checkerboard(R.xz, 100) * 0.1 + 0.1;
  c = c * float(t > 0);

  float spotlight = min(1.0, 1.5 - 0.02 * length(R.xz));

  outColor = vec4(vec3(c * spotlight), 1);

  gl_FragDepth = computeDepth(R);
}

vs.glsl

#version 450

uniform mat4 view;
uniform mat4 proj;

out vec3 nearPoint;
out vec3 farPoint;

// Grid position are in clipped space
vec3 gridPlane[6] = vec3[](vec3(1, 1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0),
                           vec3(-1, -1, 0), vec3(1, 1, 0), vec3(1, -1, 0));

vec3 UnprojectPoint(float x, float y, float z, mat4 V, mat4 P) {
  mat4 Vinv = inverse(V);
  mat4 Pinv = inverse(P);
  vec4 unprojectedPoint = Vinv * Pinv * vec4(x, y, z, 1.0);
  return unprojectedPoint.xyz / unprojectedPoint.w;
}

void main() {
  vec3 p = gridPlane[gl_VertexID].xyz;
  nearPoint = UnprojectPoint(p.x, p.y, 0.0, view, proj)
                  .xyz; // unprojecting on the near plane
  farPoint = UnprojectPoint(p.x, p.y, 1.0, view, proj)
                 .xyz;        // unprojecting on the far plane
  gl_Position = vec4(p, 1.0); // using directly the clipped coordinates
}

Hi, Josef. The default shaders for polydata can be found here:

https://gitlab.kitware.com/vtk/vtk/-/blob/master/Rendering/OpenGL2/glsl/vtkPolyDataVS.glsl
https://gitlab.kitware.com/vtk/vtk/-/blob/master/Rendering/OpenGL2/glsl/vtkPolyDataFS.glsl

When they are filled in by VTK, they look something like this:

vertex

#version 150
#ifdef GL_ES
#if __VERSION__ == 300
#define attribute in
#define varying out
#endif // 300
#else // GL_ES
#define highp
#define mediump
#define lowp
#if __VERSION__ == 150
#define attribute in
#define varying out
#endif
#endif // GL_ES


/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPolyDataVS.glsl

  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.

=========================================================================*/

attribute vec4 vertexMC;

// frag position in VC
varying vec4 vertexVCVSOutput;

// optional normal declaration
//VTK::Normal::Dec
varying vec3 myNormalMCVSOutput;


// extra lighting parameters
//VTK::Light::Dec

// Texture coordinates
//VTK::TCoord::Dec

// material property values
varying vec4 vertexColorVSOutput;
attribute vec4 scalarColor;

// clipping plane vars
//VTK::Clip::Dec

// camera and actor matrix values
uniform mat4 MCDCMatrix;
uniform mat4 MCVCMatrix;

// Apple Bug
//VTK::PrimID::Dec

// Value raster
//VTK::ValuePass::Dec

void main()
{
  vertexColorVSOutput = scalarColor;

  //VTK::Normal::Impl
  myNormalMCVSOutput = normalMC;


  //VTK::TCoord::Impl

  //VTK::Clip::Impl

  //VTK::PrimID::Impl

  vertexVCVSOutput = MCVCMatrix * vertexMC;
  gl_Position = MCDCMatrix * vertexMC;


  //VTK::ValuePass::Impl

  //VTK::Light::Impl
}
 

fragment

#version 150
#ifdef GL_ES
#if __VERSION__ == 300
#define varying in
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
precision highp sampler2D;
precision highp sampler3D;
#else
precision mediump float;
precision mediump sampler2D;
precision mediump sampler3D;
#endif
#define texelFetchBuffer texelFetch
#define texture1D texture
#define texture2D texture
#define texture3D texture
#endif // 300
#else // GL_ES
#define highp
#define mediump
#define lowp
#if __VERSION__ == 150
#define varying in
#define texelFetchBuffer texelFetch
#define texture1D texture
#define texture2D texture
#define texture3D texture
#endif
#if __VERSION__ == 120
#extension GL_EXT_gpu_shader4 : require
#endif
#endif // GL_ES


/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPolyDataFS.glsl

  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.

=========================================================================*/
// Template for the polydata mappers fragment shader

uniform int PrimitiveIDOffset;

// VC position of this fragment
varying vec4 vertexVCVSOutput;

// optional color passed in from the vertex shader, vertexColor
uniform float ambientIntensity; // the material ambient
uniform float diffuseIntensity; // the material diffuse
uniform float opacityUniform; // the fragment opacity
uniform vec3 ambientColorUniform; // ambient color
uniform vec3 diffuseColorUniform; // diffuse color
uniform float specularIntensity; // the material specular intensity
uniform vec3 specularColorUniform; // intensity weighted color
uniform float specularPowerUniform;
varying vec4 vertexColorVSOutput;


// optional surface normal declaration
uniform int cameraParallel;
;


// extra lighting parameters
uniform vec3 lightColor0;


// Texture maps
//VTK::TMap::Dec

// Texture coordinates
//VTK::TCoord::Dec

// picking support
//VTK::Picking::Dec

// Depth Peeling Support
//VTK::DepthPeeling::Dec

// clipping plane vars
//VTK::Clip::Dec

// the output of this shader
out vec4 fragOutput0;


// Apple Bug
//VTK::PrimID::Dec

// handle coincident offsets
//VTK::Coincident::Dec

// Value raster
//VTK::ValuePass::Dec

void main()
{
  // VC position of this fragment. This should not branch/return/discard.
  vec4 vertexVC = vertexVCVSOutput;

  // Place any calls that require uniform flow (e.g. dFdx) here.
  vec3 fdx = vec3(dFdx(vertexVC.x),dFdx(vertexVC.y),dFdx(vertexVC.z));
  vec3 fdy = vec3(dFdy(vertexVC.x),dFdy(vertexVC.y),dFdy(vertexVC.z));
  //VTK::UniformFlow::Impl


  // Set gl_FragDepth here (gl_FragCoord.z by default)
  //VTK::Depth::Impl

  // Early depth peeling abort:
  //VTK::DepthPeeling::PreColor

  // Apple Bug
  //VTK::PrimID::Impl

  //VTK::Clip::Impl

  //VTK::ValuePass::Impl

    vec3 specularColor = specularIntensity * specularColorUniform;
  float specularPower = specularPowerUniform;
  vec3 ambientColor = ambientIntensity * vertexColorVSOutput.rgb;
  vec3 diffuseColor = diffuseIntensity * vertexColorVSOutput.rgb;
  float opacity = opacityUniform * vertexColorVSOutput.a;

  // Generate the normal if we are not passed in one
  fdx = normalize(fdx);
  fdy = normalize(fdy);
  vec3 normalVCVSOutput = normalize(cross(fdx,fdy));
  if (cameraParallel == 1 && normalVCVSOutput.z < 0.0) { normalVCVSOutput = -1.0*normalVCVSOutput; }
  if (cameraParallel == 0 && dot(normalVCVSOutput,vertexVC.xyz) > 0.0) { normalVCVSOutput = -1.0*normalVCVSOutput; }
  diffuseColor = vec4(0.0, 1.0, 0.0, );


    float df = max(0.0,normalVCVSOutput.z);
  float sf = pow(df, specularPower);
  vec3 diffuse = df * diffuseColor * lightColor0;
  vec3 specular = sf * specularColor * lightColor0;
  fragOutput0 = vec4(ambientColor + diffuse + specular, opacity);
  //VTK::Light::Impl


  //VTK::TCoord::Impl

  if (fragOutput0.a <= 0.0)
    {
    discard;
    }

  //VTK::DepthPeeling::Impl

  //VTK::Picking::Impl

  // handle coincident offsets
  //VTK::Coincident::Impl
}

For each shader, you’ll need to choose a place to insert your own code. Everything before your main() should go in one of the //VTK::something::Dec sections. The contents of your main() should go in one of the //VTK::something::Impl sections.

A tricky part will be to get the correct matrices for your view and proj. I tried using MCVCMatrix and MCDCMatrix and did see a grid, but something was clearly not right.

I hope that helps.

Dave