forked from Kitware/VTK
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vtkOpenGLImageGradient.cxx
188 lines (160 loc) · 5.81 KB
/
vtkOpenGLImageGradient.cxx
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*=========================================================================
Program: Visualization Toolkit
Module: vtkOpenGLImageGradient.cxx
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 "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 "vtkStreamingDemandDrivenPipeline.h"
#include "vtkShaderProgram.h"
#include <algorithm> // for std::nth_element
vtkStandardNewMacro(vtkOpenGLImageGradient);
//-----------------------------------------------------------------------------
// Construct an instance of vtkOpenGLImageGradient fitler.
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 = 0;
}
}
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
virtual void InitializeShaderUniforms(vtkShaderProgram *program)
{
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
virtual void UpdateShaderUniforms(
vtkShaderProgram * /* program */, int /* zExtent */) {};
double *Spacing;
vtkOpenGLGradientCB() {};
virtual ~vtkOpenGLGradientCB() {};
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))
{
void *inPtr;
vtkDataArray *inArray = this->GetInputArrayToProcess(0,inputVector);
outData[0]->GetPointData()->GetScalars()->SetName(inArray->GetName());
inPtr = inArray->GetVoidPointer(0);
// The ouptut 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 execte 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(),
"");
}