File: vtkOpenGLImageGradient.cxx

package info (click to toggle)
vtk9 9.5.2%2Bdfsg3-7
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 206,000 kB
  • sloc: cpp: 2,336,570; ansic: 327,116; python: 111,200; yacc: 4,104; java: 3,977; sh: 3,032; xml: 2,771; perl: 2,189; lex: 1,787; makefile: 181; javascript: 165; objc: 153; tcl: 59
file content (165 lines) | stat: -rw-r--r-- 5,512 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
#include "vtkOpenGLImageGradient.h"

#include "vtkOpenGLImageAlgorithmHelper.h"

#include "vtkCellData.h"
#include "vtkDataArray.h"
#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkShaderProgram.h"
#include "vtkStreamingDemandDrivenPipeline.h"

#include <algorithm> // for std::nth_element

VTK_ABI_NAMESPACE_BEGIN
vtkStandardNewMacro(vtkOpenGLImageGradient);

//------------------------------------------------------------------------------
// Construct an instance of vtkOpenGLImageGradient filter.
vtkOpenGLImageGradient::vtkOpenGLImageGradient()
{
  // for GPU we do not want threading
  this->NumberOfThreads = 1;
  this->EnableSMP = false;
  this->Helper = vtkOpenGLImageAlgorithmHelper::New();
}

//------------------------------------------------------------------------------
vtkOpenGLImageGradient::~vtkOpenGLImageGradient()
{
  if (this->Helper)
  {
    this->Helper->Delete();
    this->Helper = nullptr;
  }
}

void vtkOpenGLImageGradient::SetRenderWindow(vtkRenderWindow* renWin)
{
  this->Helper->SetRenderWindow(renWin);
}

//------------------------------------------------------------------------------
void vtkOpenGLImageGradient::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);

  os << indent << "Helper: ";
  this->Helper->PrintSelf(os, indent);
}

// this is used as a callback by the helper to set shader parameters
// before running and to update them on each slice
class vtkOpenGLGradientCB : public vtkOpenGLImageAlgorithmCallback
{
public:
  // initialize the spacing
  void InitializeShaderUniforms(vtkShaderProgram* program) override
  {
    float sp[3];
    sp[0] = this->Spacing[0];
    sp[1] = this->Spacing[1];
    sp[2] = this->Spacing[2];
    program->SetUniform3f("spacing", sp);
  }

  // no uniforms change on a per slice basis so empty
  void UpdateShaderUniforms(vtkShaderProgram* /* program */, int /* zExtent */) override {}

  double* Spacing;
  vtkOpenGLGradientCB() = default;
  ~vtkOpenGLGradientCB() override = default;

private:
  vtkOpenGLGradientCB(const vtkOpenGLGradientCB&) = delete;
  void operator=(const vtkOpenGLGradientCB&) = delete;
};

//------------------------------------------------------------------------------
// This method contains the first switch statement that calls the correct
// templated function for the input and output region types.
void vtkOpenGLImageGradient::ThreadedRequestData(vtkInformation* vtkNotUsed(request),
  vtkInformationVector** inputVector, vtkInformationVector* vtkNotUsed(outputVector),
  vtkImageData*** inData, vtkImageData** outData, int outExt[6], int vtkNotUsed(id))
{
  vtkDataArray* inArray = this->GetInputArrayToProcess(0, inputVector);
  outData[0]->GetPointData()->GetScalars()->SetName(inArray->GetName());

  // The output scalar type must be double to store proper gradients.
  if (outData[0]->GetScalarType() != VTK_DOUBLE)
  {
    vtkErrorMacro(
      "Execute: output ScalarType is " << outData[0]->GetScalarType() << "but must be double.");
    return;
  }

  // Gradient makes sense only with one input component.  This is not
  // a Jacobian filter.
  if (inArray->GetNumberOfComponents() != 1)
  {
    vtkErrorMacro("Execute: input has more than one component. "
                  "The input to gradient should be a single component image. "
                  "Think about it. If you insist on using a color image then "
                  "run it though RGBToHSV then ExtractComponents to get the V "
                  "components. That's probably what you want anyhow.");
    return;
  }

  vtkOpenGLGradientCB cb;
  cb.Spacing = inData[0][0]->GetSpacing();

  // build the fragment shader for 2D or 3D gradient
  std::string fragShader =
    "//VTK::System::Dec\n"
    "varying vec2 tcoordVSOutput;\n"
    "uniform sampler3D inputTex1;\n"
    "uniform float zPos;\n"
    "uniform vec3 spacing;\n"
    "uniform float inputScale;\n"
    "uniform float inputShift;\n"
    "//VTK::Output::Dec\n"
    "void main(void) {\n"
    "  float dx = textureOffset(inputTex1, vec3(tcoordVSOutput, zPos), ivec3(1,0,0)).r\n"
    "    - textureOffset(inputTex1, vec3(tcoordVSOutput, zPos), ivec3(-1,0,0)).r;\n"
    "  dx = inputScale*0.5*dx/spacing.x;\n"
    "  float dy = textureOffset(inputTex1, vec3(tcoordVSOutput, zPos), ivec3(0,1,0)).r\n"
    "    - textureOffset(inputTex1, vec3(tcoordVSOutput, zPos), ivec3(0,-1,0)).r;\n"
    "  dy = inputScale*0.5*dy/spacing.y;\n";

  if (this->Dimensionality == 3)
  {
    fragShader +=
      "  float dz = textureOffset(inputTex1, vec3(tcoordVSOutput, zPos), ivec3(0,0,1)).r\n"
      "    - textureOffset(inputTex1, vec3(tcoordVSOutput, zPos), ivec3(0,0,-1)).r;\n"
      "  dz = inputScale*0.5*dz/spacing.z;\n"
      "  gl_FragData[0] = vec4(dx, dy, dz, 1.0);\n"
      "}\n";
  }
  else
  {
    fragShader += "  gl_FragData[0] = vec4(dx, dy, 0.0, 1.0);\n"
                  "}\n";
  }

  // call the helper to execute this code
  this->Helper->Execute(&cb, inData[0][0], inArray, outData[0], outExt,

    "//VTK::System::Dec\n"
    "attribute vec4 vertexMC;\n"
    "attribute vec2 tcoordMC;\n"
    "varying vec2 tcoordVSOutput;\n"
    "void main() {\n"
    "  tcoordVSOutput = tcoordMC;\n"
    "  gl_Position = vertexMC;\n"
    "}\n",

    fragShader.c_str(),

    "");
}
VTK_ABI_NAMESPACE_END