VTK
vtkVolumeShaderComposer.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkVolumeShaderComposer.h
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 #ifndef vtkVolumeShaderComposer_h
17 #define vtkVolumeShaderComposer_h
18 #include <vtkCamera.h>
20 #include <vtkRenderer.h>
21 #include <vtkVolume.h>
22 #include <vtkVolumeInputHelper.h>
23 #include <vtkVolumeMapper.h>
24 #include <vtkVolumeProperty.h>
25 #include <vtkVolumeTexture.h>
26 
27 #include <map>
28 #include <sstream>
29 #include <string>
30 
31 namespace {
32  bool HasGradientOpacity(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs)
33  {
34  for (auto& item : inputs)
35  {
36  vtkVolumeProperty* volProp = item.second.Volume->GetProperty();
37  const bool gradOp = volProp->HasGradientOpacity();
38  if (gradOp)
39  return true;
40  }
41  return false;
42  }
43 
44  bool HasLighting(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs)
45  {
46  for (auto& item : inputs)
47  {
48  vtkVolumeProperty* volProp = item.second.Volume->GetProperty();
49  const bool lighting = volProp->GetShade() == 1;
50  if (lighting)
51  return true;
52  }
53  return false;
54  }
55 
56  const std::string ArrayBaseName(const std::string& arrayName)
57  {
58  const std::string base = arrayName.substr(0, arrayName.length() - 3);
59  return base;
60  }
61 }
62 
63 // NOTE:
64 // In this code, we referred to various spaces described below:
65 // Object space: Raw coordinates in space defined by volume matrix
66 // Dataset space: Raw coordinates
67 // Eye space: Coordinates in eye space (as referred in computer graphics)
68 
69 namespace vtkvolume
70 {
71  //--------------------------------------------------------------------------
73  vtkVolumeMapper* vtkNotUsed(mapper),
74  vtkVolume* vtkNotUsed(vol))
75  {
76  return std::string(
77  " //Transform vertex (data coordinates) to clip coordinates\n"
78  " // p_clip = T_ProjViewModel * T_dataToWorld * p_data\n"
79  " vec4 pos = in_projectionMatrix * in_modelViewMatrix * in_volumeMatrix[0] *\n"
80  " vec4(in_vertexPos.xyz, 1.0);\n"
81  " gl_Position = pos;\n");
82  }
83 
84  //--------------------------------------------------------------------------
86  vtkVolumeMapper* vtkNotUsed(mapper),
87  vtkVolume* vtkNotUsed(vol))
88  {
89  return std::string(
90  " // Transform vertex (data coordinates) to texture coordinates.\n"
91  " // p_texture = T_dataToTex * p_data\n"
92  " vec3 uvx = sign(in_cellSpacing[0]) * (in_inverseTextureDatasetMatrix[0] *\n"
93  " vec4(in_vertexPos, 1.0)).xyz;\n"
94  "\n"
95  " // For point dataset, we offset the texture coordinate\n"
96  " // to account for OpenGL treating voxel at the center of the cell.\n"
97  " // Transform cell tex-coordinates to point tex-coordinates (cellToPoint\n"
98  " // is an identity matrix in the case of cell data).\n"
99  " ip_textureCoords = (in_cellToPoint[0] * vec4(uvx, 1.0)).xyz;\n"
100  " ip_inverseTextureDataAdjusted = in_cellToPoint[0] * in_inverseTextureDatasetMatrix[0];\n");
101  }
102 
103  //--------------------------------------------------------------------------
105  vtkVolumeMapper* mapper,
106  vtkVolume* vtkNotUsed(vol),
107  bool multipleInputs)
108  {
109  auto gpuMapper = vtkGPUVolumeRayCastMapper::SafeDownCast(mapper);
110  const int numInputs = gpuMapper->GetInputCount();
111 
112  std::ostringstream ss;
113  ss <<
114  "uniform vec3 in_cellSpacing["<< numInputs <<"];\n"
115  "uniform mat4 in_modelViewMatrix;\n"
116  "uniform mat4 in_projectionMatrix;\n";
117 
118  const int numTransf = multipleInputs ? numInputs + 1 : 1;
119  ss <<
120  "uniform mat4 in_volumeMatrix[" << numTransf << "];\n"
121  "uniform mat4 in_inverseTextureDatasetMatrix[" << numTransf << "];\n"
122  "uniform mat4 in_cellToPoint[" << numTransf << "];\n"
123  "\n"
124  "//This variable could be 'invariant varying' but it is declared\n"
125  "//as 'varying' to avoid compiler compatibility issues.\n"
126  "varying mat4 ip_inverseTextureDataAdjusted;\n";
127 
128  return ss.str();
129  }
130 
131  //--------------------------------------------------------------------------
133  vtkVolumeMapper* mapper,
135  int vtkNotUsed(numberOfLights),
136  int lightingComplexity,
137  int noOfComponents,
138  int independentComponents)
139  {
140  const int numInputs = static_cast<int>(inputs.size());
141 
142  std::ostringstream toShaderStr;
143  toShaderStr <<
144  "uniform sampler3D in_volume[" << numInputs <<"];\n";
145 
146  toShaderStr <<
147  "uniform vec4 in_volume_scale[" << numInputs << "];\n"
148  "uniform vec4 in_volume_bias[" << numInputs << "];\n";
149 
150  toShaderStr <<
151  "uniform int in_noOfComponents;\n"
152  "uniform int in_independentComponents;\n"
153  "\n"
154  "uniform sampler2D in_noiseSampler;\n"
155  "#ifndef GL_ES\n"
156  "uniform sampler2D in_depthSampler;\n"
157  "#endif\n"
158  "\n"
159  "// Camera position\n"
160  "uniform vec3 in_cameraPos;\n";
161 
162  // For multiple inputs (numInputs > 1), an additional transformation is
163  // needed for the bounding-box.
164  const int numTransf = (numInputs > 1) ? numInputs + 1 :
165  1;
166  toShaderStr <<
167  "uniform mat4 in_volumeMatrix[" << numTransf << "];\n"
168  "uniform mat4 in_inverseVolumeMatrix[" << numTransf << "];\n"
169  "uniform mat4 in_textureDatasetMatrix[" << numTransf << "];\n"
170  "uniform mat4 in_inverseTextureDatasetMatrix[" << numTransf << "];\n"
171  "uniform mat4 in_textureToEye[" << numTransf << "];\n"
172  "uniform vec3 in_texMin[" << numTransf << "];\n"
173  "uniform vec3 in_texMax[" << numTransf <<"];\n"
174  "uniform mat4 in_cellToPoint[" << numTransf <<"];\n";
175 
176  toShaderStr <<
177  "// view and model matrices\n"
178  "uniform mat4 in_projectionMatrix;\n"
179  "uniform mat4 in_inverseProjectionMatrix;\n"
180  "uniform mat4 in_modelViewMatrix;\n"
181  "uniform mat4 in_inverseModelViewMatrix;\n"
182  "varying mat4 ip_inverseTextureDataAdjusted;\n"
183  "\n"
184  "// Ray step size\n"
185  "uniform vec3 in_cellStep[" << numInputs << "];\n";
186 
187  toShaderStr <<
188  "uniform vec2 in_scalarsRange[" << numInputs * 4 << "];\n"
189  "uniform vec3 in_cellSpacing[" << numInputs << "];\n"
190  "\n"
191  "// Sample distance\n"
192  "uniform float in_sampleDistance;\n"
193  "\n"
194  "// Scales\n"
195  "uniform vec2 in_windowLowerLeftCorner;\n"
196  "uniform vec2 in_inverseOriginalWindowSize;\n"
197  "uniform vec2 in_inverseWindowSize;\n"
198  "uniform vec3 in_textureExtentsMax;\n"
199  "uniform vec3 in_textureExtentsMin;\n"
200  "\n"
201  "// Material and lighting\n"
202  "uniform vec3 in_diffuse[4];\n"
203  "uniform vec3 in_ambient[4];\n"
204  "uniform vec3 in_specular[4];\n"
205  "uniform float in_shininess[4];\n"
206  "\n"
207  "// Others\n"
208  "uniform bool in_useJittering;\n"
209  "vec3 g_rayJitter = vec3(0.0);\n"
210  "\n"
211  "uniform vec2 in_averageIPRange;\n";
212 
213  const bool hasGradientOpacity = HasGradientOpacity(inputs);
214  if (lightingComplexity > 0 || hasGradientOpacity)
215  {
216  toShaderStr <<
217  "uniform bool in_twoSidedLighting;\n";
218  }
219 
220  if (lightingComplexity == 3)
221  {
222  toShaderStr <<
223  "vec4 g_fragWorldPos;\n"
224  "uniform int in_numberOfLights;\n"
225  "uniform vec3 in_lightAmbientColor[6];\n"
226  "uniform vec3 in_lightDiffuseColor[6];\n"
227  "uniform vec3 in_lightSpecularColor[6];\n"
228  "uniform vec3 in_lightDirection[6];\n"
229  "uniform vec3 in_lightPosition[6];\n"
230  "uniform vec3 in_lightAttenuation[6];\n"
231  "uniform float in_lightConeAngle[6];\n"
232  "uniform float in_lightExponent[6];\n"
233  "uniform int in_lightPositional[6];\n";
234  }
235  else if (lightingComplexity == 2)
236  {
237  toShaderStr <<
238  "vec4 g_fragWorldPos;\n"
239  "uniform int in_numberOfLights;\n"
240  "uniform vec3 in_lightAmbientColor[6];\n"
241  "uniform vec3 in_lightDiffuseColor[6];\n"
242  "uniform vec3 in_lightSpecularColor[6];\n"
243  "uniform vec3 in_lightDirection[6];\n";
244  }
245  else
246  {
247  toShaderStr <<
248  "uniform vec3 in_lightAmbientColor[1];\n"
249  "uniform vec3 in_lightDiffuseColor[1];\n"
250  "uniform vec3 in_lightSpecularColor[1];\n"
251  "vec4 g_lightPosObj;\n"
252  "vec3 g_ldir;\n"
253  "vec3 g_vdir;\n"
254  "vec3 g_h;\n";
255  }
256 
257  if (noOfComponents > 1 && independentComponents)
258  {
259  toShaderStr <<
260  "uniform vec4 in_componentWeight;\n";
261  }
262 
266  glMapper->GetUseDepthPass())
267  {
268  toShaderStr <<
269  "uniform sampler2D in_depthPassSampler;\n";
270  }
271 
273  {
274  toShaderStr <<
275  "#if NUMBER_OF_CONTOURS\n"
276  "uniform float in_isosurfacesValues[NUMBER_OF_CONTOURS];\n"
277  "\n"
278  "int findIsoSurfaceIndex(float scalar, float array[NUMBER_OF_CONTOURS+2])\n"
279  "{\n"
280  " int index = NUMBER_OF_CONTOURS >> 1;\n"
281  " while (scalar > array[index]) ++index;\n"
282  " while (scalar < array[index]) --index;\n"
283  " return index;\n"
284  "}\n"
285  "#endif\n";
286  }
287 
288  return toShaderStr.str();
289  }
290 
291  //--------------------------------------------------------------------------
292  std::string BaseInit(vtkRenderer* vtkNotUsed(ren),
293  vtkVolumeMapper* mapper,
295  int lightingComplexity)
296  {
299  vtkVolume* vol = inputs.begin()->second.Volume;
300 
301  std::string shaderStr;
303  glMapper->GetUseDepthPass() && glMapper->GetBlendMode() ==
305  {
306  shaderStr += std::string("\
307  \n //\
308  \n vec2 fragTexCoord2 = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
309  \n in_inverseWindowSize;\
310  \n vec4 depthValue = texture2D(in_depthPassSampler, fragTexCoord2);\
311  \n vec4 dataPos = WindowToNDC(gl_FragCoord.x, gl_FragCoord.y, depthValue.x);\
312  \n\
313  \n // From normalized device coordinates to eye coordinates.\
314  \n // in_projectionMatrix is inversed because of way VT\
315  \n // From eye coordinates to texture coordinates\
316  \n dataPos = in_inverseTextureDatasetMatrix[0] *\
317  \n in_inverseVolumeMatrix[0] *\
318  \n in_inverseModelViewMatrix *\
319  \n in_inverseProjectionMatrix *\
320  \n dataPos;\
321  \n dataPos /= dataPos.w;\
322  \n g_dataPos = dataPos.xyz;"
323  );
324  }
325  else
326  {
327  shaderStr += std::string("\
328  \n // Get the 3D texture coordinates for lookup into the in_volume dataset\
329  \n g_dataPos = ip_textureCoords.xyz;"
330  );
331  }
332 
333  shaderStr += std::string("\
334  \n\
335  \n // Eye position in dataset space\
336  \n g_eyePosObj = in_inverseVolumeMatrix[0] * vec4(in_cameraPos, 1.0);\
337  \n\
338  \n // Getting the ray marching direction (in dataset space);\
339  \n vec3 rayDir = computeRayDirection();\
340  \n\
341  \n // Multiply the raymarching direction with the step size to get the\
342  \n // sub-step size we need to take at each raymarching step\
343  \n g_dirStep = (ip_inverseTextureDataAdjusted *\
344  \n vec4(rayDir, 0.0)).xyz * in_sampleDistance;\
345  \n\
346  \n // 2D Texture fragment coordinates [0,1] from fragment coordinates.\
347  \n // The frame buffer texture has the size of the plain buffer but \
348  \n // we use a fraction of it. The texture coordinate is less than 1 if\
349  \n // the reduction factor is less than 1.\
350  \n // Device coordinates are between -1 and 1. We need texture\
351  \n // coordinates between 0 and 1. The in_noiseSampler and in_depthSampler\
352  \n // buffers have the original size buffer.\
353  \n vec2 fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
354  \n in_inverseWindowSize;\
355  \n\
356  \n if (in_useJittering)\
357  \n {\
358  \n float jitterValue = texture2D(in_noiseSampler, fragTexCoord).x;\
359  \n g_rayJitter = g_dirStep * jitterValue;\
360  \n g_dataPos += g_rayJitter;\
361  \n }\
362  \n else\
363  \n {\
364  \n g_dataPos += g_dirStep;\
365  \n }\
366  \n\
367  \n // Flag to deternmine if voxel should be considered for the rendering\
368  \n g_skip = false;");
369 
370  if (vol->GetProperty()->GetShade() && lightingComplexity == 1)
371  {
372  shaderStr += std::string("\
373  \n // Light position in dataset space\
374  \n g_lightPosObj = (in_inverseVolumeMatrix[0] *\
375  \n vec4(in_cameraPos, 1.0));\
376  \n g_ldir = normalize(g_lightPosObj.xyz - ip_vertexPos);\
377  \n g_vdir = normalize(g_eyePosObj.xyz - ip_vertexPos);\
378  \n g_h = normalize(g_ldir + g_vdir);"
379  );
380  }
381 
382  return shaderStr;
383  }
384 
385  //--------------------------------------------------------------------------
387  vtkVolumeMapper* vtkNotUsed(mapper),
388  vtkVolume* vtkNotUsed(vol))
389  {
390  return std::string("\
391  \n g_skip = false;"
392  );
393  }
394 
395  //--------------------------------------------------------------------------
396  std::string BaseExit(vtkRenderer* vtkNotUsed(ren),
397  vtkVolumeMapper* vtkNotUsed(mapper),
398  vtkVolume* vtkNotUsed(vol))
399  {
400  return std::string();
401  }
402 
403  //--------------------------------------------------------------------------
405  int noOfComponents, int independentComponents,
406  std::map<int, std::string> gradientTableMap)
407  {
408  std::ostringstream ss;
409  ss << "uniform sampler2D " << ArrayBaseName(gradientTableMap[0])
410  << "[" << noOfComponents << "];\n";
411 
412  std::string shaderStr = ss.str();
413  if (vol->GetProperty()->HasGradientOpacity() &&
414  (noOfComponents == 1 || !independentComponents))
415  {
416  shaderStr += std::string("\
417  \nfloat computeGradientOpacity(vec4 grad)\
418  \n {\
419  \n return texture2D("+gradientTableMap[0]+", vec2(grad.w, 0.0)).r;\
420  \n }"
421  );
422  }
423  else if (noOfComponents > 1 && independentComponents &&
425  {
426  shaderStr += std::string("\
427  \nfloat computeGradientOpacity(vec4 grad, int component)\
428  \n {");
429 
430  for (int i = 0; i < noOfComponents; ++i)
431  {
432  std::ostringstream toString;
433  toString << i;
434  shaderStr += std::string("\
435  \n if (component == " + toString.str() + ")");
436 
437  shaderStr += std::string("\
438  \n {\
439  \n return texture2D("+ gradientTableMap[i] + ", vec2(grad.w, 0.0)).r;\
440  \n }"
441  );
442  }
443 
444  shaderStr += std::string("\
445  \n }");
446  }
447 
448  return shaderStr;
449  }
450 
451  //--------------------------------------------------------------------------
454  {
455  const bool hasLighting = HasLighting(inputs);
456  const bool hasGradientOp = HasGradientOpacity(inputs);
457 
458  std::string shaderStr;
459  if (hasLighting && !hasGradientOp)
460  {
461  shaderStr += std::string(
462  "// c is short for component\n"
463  "vec4 computeGradient(in vec3 texPos, in int c, in sampler3D volume,in int index)\n"
464  "{\n"
465  " // Approximate Nabla(F) derivatives with central differences.\n"
466  " vec3 g1; // F_front\n"
467  " vec3 g2; // F_back\n"
468  " vec3 xvec = vec3(in_cellStep[index].x, 0.0, 0.0);\n"
469  " vec3 yvec = vec3(0.0, in_cellStep[index].y, 0.0);\n"
470  " vec3 zvec = vec3(0.0, 0.0, in_cellStep[index].z);\n"
471  " g1.x = texture3D(volume, vec3(texPos + xvec))[c];\n"
472  " g1.y = texture3D(volume, vec3(texPos + yvec))[c];\n"
473  " g1.z = texture3D(volume, vec3(texPos + zvec))[c];\n"
474  " g2.x = texture3D(volume, vec3(texPos - xvec))[c];\n"
475  " g2.y = texture3D(volume, vec3(texPos - yvec))[c];\n"
476  " g2.z = texture3D(volume, vec3(texPos - zvec))[c];\n"
477  "\n"
478  " // Apply scale and bias to the fetched values.\n"
479  " g1 = g1 * in_volume_scale[index][c] + in_volume_bias[index][c];\n"
480  " g2 = g2 * in_volume_scale[index][c] + in_volume_bias[index][c];\n"
481  "\n"
482  " // Central differences: (F_front - F_back) / 2h\n"
483  " // This version of computeGradient() is only used for lighting\n"
484  " // calculations (only direction matters), hence the difference is\n"
485  " // not scaled by 2h and a dummy gradient mag is returned (-1.).\n"
486  " return vec4((g1 - g2) / in_cellSpacing[index], -1.0);\n"
487  "}\n");
488  }
489  else if (hasGradientOp)
490  {
491  shaderStr += std::string(
492  "// c is short for component\n"
493  "vec4 computeGradient(in vec3 texPos, in int c, in sampler3D volume, in int index)\n"
494  "{\n"
495  " // Approximate Nabla(F) derivatives with central differences.\n"
496  " vec3 g1; // F_front\n"
497  " vec3 g2; // F_back\n"
498  " vec3 xvec = vec3(in_cellStep[index].x, 0.0, 0.0);\n"
499  " vec3 yvec = vec3(0.0, in_cellStep[index].y, 0.0);\n"
500  " vec3 zvec = vec3(0.0, 0.0, in_cellStep[index].z);\n"
501  " g1.x = texture3D(volume, vec3(texPos + xvec))[c];\n"
502  " g1.y = texture3D(volume, vec3(texPos + yvec))[c];\n"
503  " g1.z = texture3D(volume, vec3(texPos + zvec))[c];\n"
504  " g2.x = texture3D(volume, vec3(texPos - xvec))[c];\n"
505  " g2.y = texture3D(volume, vec3(texPos - yvec))[c];\n"
506  " g2.z = texture3D(volume, vec3(texPos - zvec))[c];\n"
507  "\n"
508  " // Apply scale and bias to the fetched values.\n"
509  " g1 = g1 * in_volume_scale[index][c] + in_volume_bias[index][c];\n"
510  " g2 = g2 * in_volume_scale[index][c] + in_volume_bias[index][c];\n"
511  "\n"
512  " // Scale values the actual scalar range.\n"
513  " float range = in_scalarsRange[c][1] - in_scalarsRange[c][0];\n"
514  " g1 = in_scalarsRange[c][0] + range * g1;\n"
515  " g2 = in_scalarsRange[c][0] + range * g2;\n"
516  "\n"
517  " // Central differences: (F_front - F_back) / 2h\n"
518  " g2 = g1 - g2;\n"
519  "\n"
520  " float avgSpacing = (in_cellSpacing[index].x +\n"
521  " in_cellSpacing[index].y + in_cellSpacing[index].z) / 3.0;\n"
522  " vec3 aspect = in_cellSpacing[index] * 2.0 / avgSpacing;\n"
523  " g2 /= aspect;\n"
524  " float grad_mag = length(g2);\n"
525  "\n"
526  " // Handle normalizing with grad_mag == 0.0\n"
527  " g2 = grad_mag > 0.0 ? normalize(g2) : vec3(0.0);\n"
528  "\n"
529  " // Since the actual range of the gradient magnitude is unknown,\n"
530  " // assume it is in the range [0, 0.25 * dataRange].\n"
531  " range = range != 0 ? range : 1.0;\n"
532  " grad_mag = grad_mag / (0.25 * range);\n"
533  " grad_mag = clamp(grad_mag, 0.0, 1.0);\n"
534  "\n"
535  " return vec4(g2.xyz, grad_mag);\n"
536  "}\n");
537  }
538  else
539  {
540  shaderStr += std::string(
541  "vec4 computeGradient(in vec3 texPos, in int c, in sampler3D volume, in int index)\n"
542  "{\n"
543  " return vec4(0.0);\n"
544  "}\n");
545  }
546 
547  return shaderStr;
548  }
549 
550  //--------------------------------------------------------------------------
552  vtkVolumeMapper* mapper,
553  vtkVolume* vol,
554  int noOfComponents,
555  int independentComponents,
556  int vtkNotUsed(numberOfLights),
557  int lightingComplexity)
558  {
559  vtkVolumeProperty* volProperty = vol->GetProperty();
560  std::string shaderStr = std::string("\
561  \nvec4 computeLighting(vec4 color, int component)\
562  \n {\
563  \n vec4 finalColor = vec4(0.0);"
564  );
565 
566  // Shading for composite blending only
567  int const shadeReqd = volProperty->GetShade() &&
570 
571  int const transferMode = volProperty->GetTransferFunctionMode();
572 
573  if (shadeReqd || volProperty->HasGradientOpacity())
574  {
575  switch (transferMode)
576  {
577  case vtkVolumeProperty::TF_1D: shaderStr += std::string(
578  " // Compute gradient function only once\n"
579  " vec4 gradient = computeGradient(g_dataPos, component, in_volume[0], 0);\n");
580  break;
582  shaderStr += std::string(
583  " // TransferFunction2D is enabled so the gradient for\n"
584  " // each component has already been cached\n"
585  " vec4 gradient = g_gradients_0[component];\n");
586  break;
587  }
588  }
589 
590  if (shadeReqd)
591  {
592  if (lightingComplexity == 1)
593  {
594  shaderStr += std::string("\
595  \n vec3 diffuse = vec3(0.0);\
596  \n vec3 specular = vec3(0.0);\
597  \n vec3 normal = gradient.xyz;\
598  \n float normalLength = length(normal);\
599  \n if (normalLength > 0.0)\
600  \n {\
601  \n normal = normalize(normal);\
602  \n }\
603  \n else\
604  \n {\
605  \n normal = vec3(0.0, 0.0, 0.0);\
606  \n }\
607  \n float nDotL = dot(normal, g_ldir);\
608  \n float nDotH = dot(normal, g_h);\
609  \n if (nDotL < 0.0 && in_twoSidedLighting)\
610  \n {\
611  \n nDotL = -nDotL;\
612  \n }\
613  \n if (nDotH < 0.0 && in_twoSidedLighting)\
614  \n {\
615  \n nDotH = -nDotH;\
616  \n }\
617  \n if (nDotL > 0.0)\
618  \n {\
619  \n diffuse = nDotL * in_diffuse[component] *\
620  \n in_lightDiffuseColor[0] * color.rgb;\
621  \n }\
622  \n specular = pow(nDotH, in_shininess[component]) *\
623  \n in_specular[component] *\
624  \n in_lightSpecularColor[0];\
625  \n // For the headlight, ignore the light's ambient color\
626  \n // for now as it is causing the old mapper tests to fail\
627  \n finalColor.xyz = in_ambient[component] * color.rgb +\
628  \n diffuse + specular;"
629  );
630  }
631  else if (lightingComplexity == 2)
632  {
633  shaderStr += std::string("\
634  \n g_fragWorldPos = in_modelViewMatrix * in_volumeMatrix[0] *\
635  \n in_textureDatasetMatrix[0] * vec4(-g_dataPos, 1.0);\
636  \n if (g_fragWorldPos.w != 0.0)\
637  \n {\
638  \n g_fragWorldPos /= g_fragWorldPos.w;\
639  \n }\
640  \n vec3 vdir = normalize(g_fragWorldPos.xyz);\
641  \n vec3 normal = gradient.xyz;\
642  \n vec3 ambient = vec3(0.0);\
643  \n vec3 diffuse = vec3(0.0);\
644  \n vec3 specular = vec3(0.0);\
645  \n float normalLength = length(normal);\
646  \n if (normalLength > 0.0)\
647  \n {\
648  \n normal = normalize((in_textureToEye[0] * vec4(normal, 0.0)).xyz);\
649  \n }\
650  \n else\
651  \n {\
652  \n normal = vec3(0.0, 0.0, 0.0);\
653  \n }\
654  \n for (int lightNum = 0; lightNum < in_numberOfLights; lightNum++)\
655  \n {\
656  \n vec3 ldir = in_lightDirection[lightNum].xyz;\
657  \n vec3 h = normalize(ldir + vdir);\
658  \n float nDotH = dot(normal, h);\
659  \n if (nDotH < 0.0 && in_twoSidedLighting)\
660  \n {\
661  \n nDotH = -nDotH;\
662  \n }\
663  \n float nDotL = dot(normal, ldir);\
664  \n if (nDotL < 0.0 && in_twoSidedLighting)\
665  \n {\
666  \n nDotL = -nDotL;\
667  \n }\
668  \n if (nDotL > 0.0)\
669  \n {\
670  \n diffuse += in_lightDiffuseColor[lightNum] * nDotL;\
671  \n }\
672  \n if (nDotH > 0.0)\
673  \n {\
674  \n specular = in_lightSpecularColor[lightNum] *\
675  \n pow(nDotH, in_shininess[component]);\
676  \n }\
677  \n ambient += in_lightAmbientColor[lightNum];\
678  \n }\
679  \n finalColor.xyz = in_ambient[component] * ambient +\
680  \n in_diffuse[component] * diffuse * color.rgb +\
681  \n in_specular[component] * specular;"
682  );
683  }
684  else if (lightingComplexity == 3)
685  {
686  shaderStr += std::string("\
687  \n g_fragWorldPos = in_modelViewMatrix * in_volumeMatrix[0] *\
688  \n in_textureDatasetMatrix[0] * vec4(g_dataPos, 1.0);\
689  \n if (g_fragWorldPos.w != 0.0)\
690  \n {\
691  \n g_fragWorldPos /= g_fragWorldPos.w;\
692  \n }\
693  \n vec3 viewDirection = normalize(-g_fragWorldPos.xyz);\
694  \n vec3 ambient = vec3(0,0,0);\
695  \n vec3 diffuse = vec3(0,0,0);\
696  \n vec3 specular = vec3(0,0,0);\
697  \n vec3 vertLightDirection;\
698  \n vec3 normal = normalize((in_textureToEye[0] * vec4(gradient.xyz, 0.0)).xyz);\
699  \n vec3 lightDir;\
700  \n for (int lightNum = 0; lightNum < in_numberOfLights; lightNum++)\
701  \n {\
702  \n float attenuation = 1.0;\
703  \n // directional\
704  \n lightDir = in_lightDirection[lightNum];\
705  \n if (in_lightPositional[lightNum] == 0)\
706  \n {\
707  \n vertLightDirection = lightDir;\
708  \n }\
709  \n else\
710  \n {\
711  \n vertLightDirection = (g_fragWorldPos.xyz - in_lightPosition[lightNum]);\
712  \n float distance = length(vertLightDirection);\
713  \n vertLightDirection = normalize(vertLightDirection);\
714  \n attenuation = 1.0 /\
715  \n (in_lightAttenuation[lightNum].x\
716  \n + in_lightAttenuation[lightNum].y * distance\
717  \n + in_lightAttenuation[lightNum].z * distance * distance);\
718  \n // per OpenGL standard cone angle is 90 or less for a spot light\
719  \n if (in_lightConeAngle[lightNum] <= 90.0)\
720  \n {\
721  \n float coneDot = dot(vertLightDirection, lightDir);\
722  \n // if inside the cone\
723  \n if (coneDot >= cos(radians(in_lightConeAngle[lightNum])))\
724  \n {\
725  \n attenuation = attenuation * pow(coneDot, in_lightExponent[lightNum]);\
726  \n }\
727  \n else\
728  \n {\
729  \n attenuation = 0.0;\
730  \n }\
731  \n }\
732  \n }\
733  \n // diffuse and specular lighting\
734  \n float nDotL = dot(normal, vertLightDirection);\
735  \n if (nDotL < 0.0 && in_twoSidedLighting)\
736  \n {\
737  \n nDotL = -nDotL;\
738  \n }\
739  \n if (nDotL > 0.0)\
740  \n {\
741  \n float df = max(0.0, attenuation * nDotL);\
742  \n diffuse += (df * in_lightDiffuseColor[lightNum]);\
743  \n }\
744  \n vec3 h = normalize(vertLightDirection + viewDirection);\
745  \n float nDotH = dot(normal, h);\
746  \n if (nDotH < 0.0 && in_twoSidedLighting)\
747  \n {\
748  \n nDotH = -nDotH;\
749  \n }\
750  \n if (nDotH > 0.0)\
751  \n {\
752  \n float sf = attenuation * pow(nDotH, in_shininess[component]);\
753  \n specular += (sf * in_lightSpecularColor[lightNum]);\
754  \n }\
755  \n ambient += in_lightAmbientColor[lightNum];\
756  \n }\
757  \n finalColor.xyz = in_ambient[component] * ambient +\
758  \n in_diffuse[component] * diffuse * color.rgb +\
759  \n in_specular[component] * specular;\
760  ");
761  }
762  }
763  else
764  {
765  shaderStr += std::string(
766  "\n finalColor = vec4(color.rgb, 0.0);"
767  );
768  }
769 
770  auto glMapper = vtkOpenGLGPUVolumeRayCastMapper::SafeDownCast(mapper);
771  // For 1D transfers only (2D transfer functions hold scalar and
772  // gradient-magnitude opacities combined in the same table).
773  // For multiple inputs, a different computeGradientOpacity() signature
774  // is defined.
775  if (transferMode == vtkVolumeProperty::TF_1D &&
776  glMapper->GetInputCount() == 1)
777  {
778  if (volProperty->HasGradientOpacity() &&
779  (noOfComponents == 1 || !independentComponents))
780  {
781  shaderStr += std::string("\
782  \n if (gradient.w >= 0.0)\
783  \n {\
784  \n color.a = color.a *\
785  \n computeGradientOpacity(gradient);\
786  \n }"
787  );
788  }
789  else if (noOfComponents > 1 && independentComponents &&
790  volProperty->HasGradientOpacity())
791  {
792  shaderStr += std::string("\
793  \n if (gradient.w >= 0.0)\
794  \n {\
795  \n for (int i = 0; i < in_noOfComponents; ++i)\
796  \n {\
797  \n color.a = color.a *\
798  \n computeGradientOpacity(gradient, i) * in_componentWeight[i];\
799  \n }\
800  \n }"
801  );
802  }
803  }
804 
805  shaderStr += std::string("\
806  \n finalColor.a = color.a;\
807  \n return finalColor;\
808  \n }"
809  );
810 
811  return shaderStr;
812  }
813 
814  //--------------------------------------------------------------------------
816  vtkVolumeMapper* vtkNotUsed(mapper),
817  vtkVolume* vtkNotUsed(vol),
818  int vtkNotUsed(noOfComponents))
819  {
820  if (!ren->GetActiveCamera()->GetParallelProjection())
821  {
822  return std::string("\
823  \nvec3 computeRayDirection()\
824  \n {\
825  \n return normalize(ip_vertexPos.xyz - g_eyePosObj.xyz);\
826  \n }");
827  }
828  else
829  {
830  return std::string("\
831  \nuniform vec3 in_projectionDirection;\
832  \nvec3 computeRayDirection()\
833  \n {\
834  \n return normalize((in_inverseVolumeMatrix[0] *\
835  \n vec4(in_projectionDirection, 0.0)).xyz);\
836  \n }");
837  }
838  }
839 
840  //--------------------------------------------------------------------------
842  vtkVolumeMapper* vtkNotUsed(mapper),
843  vtkVolume* vtkNotUsed(vol),
844  int noOfComponents,
845  int independentComponents,
846  std::map<int, std::string> colorTableMap)
847  {
848  std::ostringstream ss;
849  ss << "uniform sampler2D " << ArrayBaseName(colorTableMap[0])
850  << "[" << noOfComponents << "];\n";
851 
852  std::string shaderStr = ss.str();
853  if (noOfComponents == 1)
854  {
855  shaderStr += std::string("\
856  \nvec4 computeColor(vec4 scalar, float opacity)\
857  \n {\
858  \n return computeLighting(vec4(texture2D(" + colorTableMap[0] +",\
859  \n vec2(scalar.w, 0.0)).xyz, opacity), 0);\
860  \n }");
861  return shaderStr;
862  }
863  else if (noOfComponents > 1 && independentComponents)
864  {
865  std::ostringstream toString;
866 
867  shaderStr += std::string("\
868  \nvec4 computeColor(vec4 scalar, float opacity, int component)\
869  \n {");
870 
871  for (int i = 0; i < noOfComponents; ++i)
872  {
873  toString << i;
874  shaderStr += std::string("\
875  \n if (component == " + toString.str() + ")");
876 
877  shaderStr += std::string("\
878  \n {\
879  \n return computeLighting(vec4(texture2D(\
880  \n "+colorTableMap[i]);
881  shaderStr += std::string(", vec2(\
882  \n scalar[" + toString.str() + "],0.0)).xyz,\
883  \n opacity),"+toString.str()+");\
884  \n }");
885 
886  // Reset
887  toString.str("");
888  toString.clear();
889  }
890 
891  shaderStr += std::string("\n }");
892  return shaderStr;
893  }
894  else if (noOfComponents == 2 && !independentComponents)
895  {
896  shaderStr += std::string("\
897  \nvec4 computeColor(vec4 scalar, float opacity)\
898  \n {\
899  \n return computeLighting(vec4(texture2D(" + colorTableMap[0] + ",\
900  \n vec2(scalar.x, 0.0)).xyz,\
901  \n opacity), 0);\
902  \n }");
903  return shaderStr;
904  }
905  else
906  {
907  shaderStr += std::string("\
908  \nvec4 computeColor(vec4 scalar, float opacity)\
909  \n {\
910  \n return computeLighting(vec4(scalar.xyz, opacity), 0);\
911  \n }");
912  return shaderStr;
913  }
914  }
915 
916  //--------------------------------------------------------------------------
919  {
920  std::ostringstream ss;
921  int i = 0;
922  for (auto& item : inputs)
923  {
924  auto prop = item.second.Volume->GetProperty();
925  if (prop->GetTransferFunctionMode() != vtkVolumeProperty::TF_1D)
926  continue;
927 
928  auto& map = item.second.RGBTablesMap;
929  const auto numComp = map.size();
930  ss << "uniform sampler2D " << ArrayBaseName(map[0])
931  << "[" << numComp <<"];\n";
932  i++;
933  }
934 
935  ss <<
936  "vec3 computeColor(const in float scalar, const in sampler2D colorTF)\n"
937  "{\n"
938  " return texture2D(colorTF, vec2(scalar, 0)).rgb;\n"
939  "}\n";
940  return ss.str();
941  }
942 
943  //--------------------------------------------------------------------------
946  {
947  std::ostringstream ss;
948  int i = 0;
949  for (auto& item : inputs)
950  {
951  auto prop = item.second.Volume->GetProperty();
952  if (prop->GetTransferFunctionMode() != vtkVolumeProperty::TF_1D)
953  continue;
954 
955  auto& map = item.second.OpacityTablesMap;
956  const auto numComp = map.size();
957  ss << "uniform sampler2D " << ArrayBaseName(map[0])
958  << "[" << numComp << "];\n";
959  i++;
960  }
961 
962  ss <<
963  "float computeOpacity(const in float scalar, const in sampler2D opacityTF)\n"
964  "{\n"
965  " return texture2D(opacityTF, vec2(scalar, 0)).r;\n"
966  "}\n";
967  return ss.str();
968  }
969 
970  //--------------------------------------------------------------------------
973  {
974  std::ostringstream ss;
975 
976  int i = 0;
977  for (auto& item : inputs)
978  {
979  auto prop = item.second.Volume->GetProperty();
980  if (prop->GetTransferFunctionMode() != vtkVolumeProperty::TF_1D ||
981  !prop->HasGradientOpacity())
982  continue;
983 
984  auto& map = item.second.GradientOpacityTablesMap;
985  const auto numComp = map.size();
986  ss << "uniform sampler2D " << ArrayBaseName(map[0])
987  << "[" << numComp <<"];\n";
988  i++;
989  }
990 
991  ss<<
992  "float computeGradientOpacity(const in float scalar, const in sampler2D opacityTF)\n"
993  "{\n"
994  " return texture2D(opacityTF, vec2(scalar, 0)).r;\n"
995  "}\n";
996  return ss.str();
997  }
998 
999  //--------------------------------------------------------------------------
1001  vtkVolumeMapper* vtkNotUsed(mapper),
1002  vtkVolume* vtkNotUsed(vol),
1003  int noOfComponents,
1004  int independentComponents,
1005  std::map<int, std::string> opacityTableMap)
1006  {
1007  std::ostringstream ss;
1008  ss << "uniform sampler2D " << ArrayBaseName(opacityTableMap[0])
1009  << "[" << noOfComponents << "];\n";
1010 
1011  std::string shaderStr = ss.str();
1012  if (noOfComponents > 1 && independentComponents)
1013  {
1014  shaderStr += std::string("\
1015  \nfloat computeOpacity(vec4 scalar, int component)\
1016  \n{");
1017 
1018  for (int i = 0; i < noOfComponents; ++i)
1019  {
1020  std::ostringstream toString;
1021  toString << i;
1022  shaderStr += std::string("\
1023  \n if (component == " + toString.str() + ")");
1024 
1025  shaderStr += std::string("\
1026  \n {\
1027  \n return texture2D(" + opacityTableMap[i]);
1028 
1029  shaderStr += std::string(",vec2(scalar[" + toString.str() + "], 0)).r;\
1030  \n }");
1031  }
1032 
1033  shaderStr += std::string("\n}");
1034  return shaderStr;
1035  }
1036  else if (noOfComponents == 2 && !independentComponents)
1037  {
1038  shaderStr += std::string("\
1039  \nfloat computeOpacity(vec4 scalar)\
1040  \n{\
1041  \n return texture2D(" + opacityTableMap[0] + ", vec2(scalar.y, 0)).r;\
1042  \n}");
1043  return shaderStr;
1044  }
1045  else
1046  {
1047  shaderStr += std::string("\
1048  \nfloat computeOpacity(vec4 scalar)\
1049  \n{\
1050  \n return texture2D(" + opacityTableMap[0] + ", vec2(scalar.w, 0)).r;\
1051  \n}");
1052  return shaderStr;
1053  }
1054  }
1055 
1056  //--------------------------------------------------------------------------
1058  vtkVolumeMapper* vtkNotUsed(mapper),
1059  vtkVolume* vtkNotUsed(vol),
1060  int noOfComponents,
1061  int independentComponents,
1062  std::map<int, std::string> colorTableMap)
1063  {
1064  if (noOfComponents == 1)
1065  {
1066  // Single component
1067  return std::string(
1068  "vec4 computeColor(vec4 scalar, float opacity)\n"
1069  "{\n"
1070  " vec4 color = texture2D(" + colorTableMap[0] + ",\n"
1071  " vec2(scalar.w, g_gradients_0[0].w));\n"
1072  " return computeLighting(color, 0);\n"
1073  "}\n");
1074  }
1075  else if (noOfComponents > 1 && independentComponents)
1076  {
1077  // Multiple independent components
1078  std::string shaderStr;
1079  shaderStr += std::string(
1080  "vec4 computeColor(vec4 scalar, float opacity, int component)\n"
1081  "{\n");
1082 
1083  for (int i = 0; i < noOfComponents; ++i)
1084  {
1085  std::ostringstream toString;
1086  toString << i;
1087  std::string const num = toString.str();
1088  shaderStr += std::string(
1089  " if (component == " + num + ")\n"
1090  " {\n"
1091  " vec4 color = texture2D(" + colorTableMap[i] + ",\n"
1092  " vec2(scalar[" + num + "], g_gradients_0[" + num + "].w));\n"
1093  " return computeLighting(color, " + num + ");\n"
1094  " }\n");
1095  }
1096  shaderStr += std::string("}\n");
1097 
1098  return shaderStr;
1099  }
1100  else if (noOfComponents == 2 && !independentComponents)
1101  {
1102  // Dependent components (Luminance/ Opacity)
1103  return std::string(
1104  "vec4 computeColor(vec4 scalar, float opacity)\n"
1105  "{\n"
1106  " vec4 color = texture2D(" + colorTableMap[0] + ",\n"
1107  " vec2(scalar.x, g_gradients_0[0].w));\n"
1108  " return computeLighting(color, 0);\n"
1109  "}\n");
1110  }
1111  else
1112  {
1113  return std::string(
1114  "vec4 computeColor(vec4 scalar, float opacity)\n"
1115  "{\n"
1116  " return computeLighting(vec4(scalar.xyz, opacity), 0);\n"
1117  "}\n");
1118  }
1119  }
1120 
1123  {
1124  std::ostringstream ss;
1125  int i = 0;
1126  for (auto& item : inputs)
1127  {
1128  auto prop = item.second.Volume->GetProperty();
1129  if (prop->GetTransferFunctionMode() != vtkVolumeProperty::TF_2D)
1130  continue;
1131 
1132  auto& map = item.second.TransferFunctions2DMap;
1133  const auto numComp = map.size();
1134  ss << "uniform sampler2D " << ArrayBaseName(map[0])
1135  << "[" << numComp <<"];\n";
1136  i++;
1137  }
1138 
1139  return ss.str();
1140  }
1141 
1142  //--------------------------------------------------------------------------
1144  vtkVolumeMapper* vtkNotUsed(mapper),
1145  vtkVolume* vtkNotUsed(vol),
1146  int noOfComponents,
1147  int independentComponents,
1148  std::map<int, std::string> opacityTableMap)
1149  {
1150  std::ostringstream toString;
1151  if (noOfComponents > 1 && independentComponents)
1152  {
1153  // Multiple independent components
1154  toString <<
1155  "float computeOpacity(vec4 scalar, int component)\n"
1156  "{\n";
1157 
1158  for (int i = 0; i < noOfComponents; ++i)
1159  {
1160  toString <<
1161  " if (component == " << i << ")\n"
1162  " {\n"
1163  " return texture2D(" << opacityTableMap[i] << ",\n"
1164  " vec2(scalar[" << i << "], g_gradients_0[" << i << "].w)).a;\n"
1165  " }\n";
1166  }
1167 
1168  toString << "}\n";
1169  }
1170  else if (noOfComponents == 2 && !independentComponents)
1171  {
1172  // Dependent components (Luminance/ Opacity)
1173  toString <<
1174  "float computeOpacity(vec4 scalar)\n"
1175  "{\n"
1176  " return texture2D(" + opacityTableMap[0] + ",\n"
1177  " vec2(scalar.y, g_gradients_0[0].w)).a;\n"
1178  "}\n";
1179  }
1180  else
1181  {
1182  // Dependent compoennts (RGBA) || Single component
1183  toString <<
1184  "float computeOpacity(vec4 scalar)\n"
1185  "{\n"
1186  " return texture2D(" + opacityTableMap[0] + ",\n"
1187  " vec2(scalar.a, g_gradients_0[0].w)).a;\n"
1188  "}\n";
1189  }
1190  return toString.str();
1191  }
1192 
1193  //--------------------------------------------------------------------------
1195  vtkVolumeMapper* vtkNotUsed(mapper),
1196  vtkVolume* vtkNotUsed(vol))
1197  {
1198  return std::string();
1199  }
1200 
1201  //--------------------------------------------------------------------------
1203  vtkVolumeMapper* mapper,
1204  vtkVolume* vtkNotUsed(vol))
1205  {
1207  {
1208  return std::string("\
1209  \n bool l_firstValue;\
1210  \n vec4 l_maxValue;");
1211  }
1212  else if (mapper->GetBlendMode() ==
1214  {
1215  return std::string("\
1216  \n bool l_firstValue;\
1217  \n vec4 l_minValue;");
1218  }
1220  {
1221  return std::string("\
1222  \n uvec4 l_numSamples;\
1223  \n vec4 l_avgValue;");
1224  }
1225  else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
1226  {
1227  return std::string("\
1228  \n vec4 l_sumValue;");
1229  }
1230  else if (mapper->GetBlendMode() == vtkVolumeMapper::ISOSURFACE_BLEND)
1231  {
1232  return std::string("\
1233  \n int l_initialIndex = 0;\
1234  \n float l_normValues[NUMBER_OF_CONTOURS + 2];");
1235  }
1236  else
1237  {
1238  return std::string();
1239  }
1240  }
1241 
1242  //--------------------------------------------------------------------------
1244  vtkVolumeMapper* mapper,
1245  vtkVolume* vtkNotUsed(vol))
1246  {
1248  {
1249  return std::string("\
1250  \n // We get data between 0.0 - 1.0 range\
1251  \n l_firstValue = true;\
1252  \n l_maxValue = vec4(0.0);"
1253  );
1254  }
1255  else if (mapper->GetBlendMode() ==
1257  {
1258  return std::string("\
1259  \n //We get data between 0.0 - 1.0 range\
1260  \n l_firstValue = true;\
1261  \n l_minValue = vec4(1.0);"
1262  );
1263  }
1265  {
1266  return std::string("\
1267  \n //We get data between 0.0 - 1.0 range\
1268  \n l_avgValue = vec4(0.0);\
1269  \n // Keep track of number of samples\
1270  \n l_numSamples = uvec4(0);"
1271  );
1272  }
1273  else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
1274  {
1275  return std::string("\
1276  \n //We get data between 0.0 - 1.0 range\
1277  \n l_sumValue = vec4(0.0);"
1278  );
1279  }
1280  else if (mapper->GetBlendMode() == vtkVolumeMapper::ISOSURFACE_BLEND)
1281  {
1282  return std::string("\
1283  \n#if NUMBER_OF_CONTOURS\
1284  \n l_normValues[0] = -1e20; //-infinity\
1285  \n l_normValues[NUMBER_OF_CONTOURS+1] = +1e20; //+infinity\
1286  \n for (int i = 0; i < NUMBER_OF_CONTOURS; i++)\
1287  \n {\
1288  \n l_normValues[i+1] = (in_isosurfacesValues[i] - in_scalarsRange[0].x) / \
1289  \n (in_scalarsRange[0].y - in_scalarsRange[0].x);\
1290  \n }\
1291  \n#endif\
1292  ");
1293  }
1294  else
1295  {
1296  return std::string();
1297  }
1298  }
1299 
1300  //--------------------------------------------------------------------------
1302  vtkVolume* vtkNotUsed(vol),
1304  int independentComponents = 0)
1305  {
1306  const int numInputs = static_cast<int>(inputs.size());
1307  const int comp = numInputs == 1 ?
1308  // Dependent components use a single opacity lut.
1309  (!independentComponents ? 1 : numInputs) :
1310  // Independent components not supported with multiple-inputs
1311  1;
1312 
1313  std::ostringstream toShader;
1314  for (const auto& item : inputs)
1315  {
1316  auto& input = item.second;
1317  if (input.Volume->GetProperty()->HasGradientOpacity())
1318  {
1319  toShader <<
1320  "vec4 " << input.GradientCacheName << "[" << comp << "];\n";
1321  }
1322  }
1323 
1324  return toShader.str();
1325  }
1326 
1327  //--------------------------------------------------------------------------
1329  vtkVolume* vtkNotUsed(vol),
1330  int noOfComponents = 1,
1331  int independentComponents = 0)
1332  {
1333  std::ostringstream shader;
1334  if (independentComponents)
1335  {
1336  if (noOfComponents == 1)
1337  {
1338  shader <<
1339  "g_gradients_0[0] = computeGradient(g_dataPos, 0, in_volume[0], 0);\n";
1340  }
1341  else
1342  {
1343  // Multiple components
1344  shader <<
1345  "for (int comp = 0; comp < in_noOfComponents; comp++)\n"
1346  "{\n"
1347  " g_gradients_0[comp] = computeGradient(g_dataPos, comp, in_volume[0], 0);\n"
1348  "}\n";
1349  }
1350  }
1351  else
1352  {
1353  shader <<
1354  "g_gradients_0[0] = computeGradient(g_dataPos, 0, in_volume[0], 0);\n";
1355  }
1356 
1357  return shader.str();
1358  }
1359 
1360  //--------------------------------------------------------------------------
1363  {
1364  std::ostringstream toShaderStr;
1365  toShaderStr <<
1366  " if (!g_skip)\n"
1367  " {\n"
1368  " vec3 texPos;\n";
1369 
1370  switch (mapper->GetBlendMode())
1371  {
1373  default:
1374  {
1375  int i = 0;
1376  for (auto& item : inputs)
1377  {
1378  auto& input = item.second;
1379  auto property = input.Volume->GetProperty();
1380  // Transformation index. Index 0 refers to the global bounding-box.
1381  const auto idx = i + 1;
1382  toShaderStr <<
1383  // From global texture coordinates (bbox) to volume_i texture coords.
1384  // texPos = T * g_dataPos
1385  // T = T_dataToTex1 * T_worldToData * T_bboxTexToWorld;
1386  " texPos = (in_cellToPoint[" << idx << "] * in_inverseTextureDatasetMatrix[" << idx
1387  << "] * in_inverseVolumeMatrix[" << idx <<"] *\n"
1388  " in_volumeMatrix[0] * in_textureDatasetMatrix[0] * vec4(g_dataPos.xyz, 1.0)).xyz;\n"
1389  " if ((all(lessThanEqual(texPos, vec3(1.0))) &&\n"
1390  " all(greaterThanEqual(texPos, vec3(0.0)))))\n"
1391  " {\n"
1392  " vec4 scalar = texture3D(in_volume[" << i << "], texPos);\n"
1393  " scalar = scalar * in_volume_scale[" << i << "] + in_volume_bias[" << i << "];\n"
1394  " scalar = vec4(scalar.r);\n"
1395  " g_srcColor = vec4(0.0);\n";
1396 
1397  if (property->GetTransferFunctionMode() == vtkVolumeProperty::TF_1D)
1398  {
1399  toShaderStr <<
1400  " g_srcColor.a = computeOpacity(scalar.r," << input.OpacityTablesMap[0] << ");\n"
1401  " if (g_srcColor.a > 0.0)\n"
1402  " {\n"
1403  " g_srcColor.rgb = computeColor(scalar.r, " << input.RGBTablesMap[0] << ");\n";
1404 
1405  if (property->HasGradientOpacity())
1406  {
1407  const auto& grad = input.GradientCacheName;
1408  toShaderStr <<
1409  " " << grad << "[0] = computeGradient(texPos, 0, " << "in_volume[" << i << "], " << i << ");\n"
1410  " if ("<< grad << "[0].w >= 0.0)\n"
1411  " {\n"
1412  " g_srcColor.a *= computeGradientOpacity(" << grad << "[0].w, "
1413  << input.GradientOpacityTablesMap[0] << ");\n"
1414  " }\n";
1415  }
1416  }
1417  else if (property->GetTransferFunctionMode() == vtkVolumeProperty::TF_2D)
1418  {
1419  const auto& grad = input.GradientCacheName;
1420  toShaderStr <<
1421  // Sample 2DTF directly
1422  " " << grad << "[0] = computeGradient(texPos, 0, " << "in_volume[" << i << "], " << i << ");\n"
1423  " g_srcColor = texture2D(" << input.TransferFunctions2DMap[0] << ", vec2(scalar.r, " << input.GradientCacheName << "[0].w));\n"
1424  " if (g_srcColor.a > 0.0)\n"
1425  " {\n";
1426  }
1427 
1428  toShaderStr <<
1429  " g_srcColor.rgb *= g_srcColor.a;\n"
1430  " g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;\n"
1431  " }\n"
1432  " }\n\n";
1433 
1434  i++;
1435  }
1436  }
1437  break;
1438  }
1439  toShaderStr <<
1440  " }\n";
1441 
1442  return toShaderStr.str();
1443  }
1444 
1445  //--------------------------------------------------------------------------
1447  vtkVolumeMapper* mapper,
1448  vtkVolume* vtkNotUsed(vol),
1449  vtkImageData* maskInput,
1450  vtkVolumeTexture* mask, int maskType,
1451  int noOfComponents,
1452  int independentComponents = 0)
1453  {
1454  auto glMapper = vtkOpenGLGPUVolumeRayCastMapper::SafeDownCast(mapper);
1455  std::string shaderStr = std::string("\
1456  \n if (!g_skip)\
1457  \n {\
1458  \n vec4 scalar = texture3D(in_volume[0], g_dataPos);"
1459  );
1460 
1461  // simulate old intensity textures
1462  if (noOfComponents == 1)
1463  {
1464  shaderStr += std::string("\
1465  \n scalar.r = scalar.r * in_volume_scale[0].r + in_volume_bias[0].r;\
1466  \n scalar = vec4(scalar.r);"
1467  );
1468  }
1469  else
1470  {
1471  // handle bias and scale
1472  shaderStr += std::string("\
1473  \n scalar = scalar * in_volume_scale[0] + in_volume_bias[0];"
1474  );
1475  }
1476 
1478  {
1479  if (noOfComponents > 1)
1480  {
1481  if (!independentComponents)
1482  {
1483  shaderStr += std::string("\
1484  \n if (l_maxValue.w < scalar.w || l_firstValue)\
1485  \n {\
1486  \n l_maxValue = scalar;\
1487  \n }\
1488  \n\
1489  \n if (l_firstValue)\
1490  \n {\
1491  \n l_firstValue = false;\
1492  \n }"
1493  );
1494  }
1495  else
1496  {
1497  shaderStr += std::string("\
1498  \n for (int i = 0; i < in_noOfComponents; ++i)\
1499  \n {\
1500  \n if (l_maxValue[i] < scalar[i] || l_firstValue)\
1501  \n {\
1502  \n l_maxValue[i] = scalar[i];\
1503  \n }\
1504  \n }\
1505  \n if (l_firstValue)\
1506  \n {\
1507  \n l_firstValue = false;\
1508  \n }"
1509  );
1510  }
1511  }
1512  else
1513  {
1514  shaderStr += std::string("\
1515  \n if (l_maxValue.w < scalar.x || l_firstValue)\
1516  \n {\
1517  \n l_maxValue.w = scalar.x;\
1518  \n }\
1519  \n\
1520  \n if (l_firstValue)\
1521  \n {\
1522  \n l_firstValue = false;\
1523  \n }"
1524  );
1525  }
1526  }
1528  {
1529  if (noOfComponents > 1)
1530  {
1531  if (!independentComponents)
1532  {
1533  shaderStr += std::string("\
1534  \n if (l_minValue.w > scalar.w || l_firstValue)\
1535  \n {\
1536  \n l_minValue = scalar;\
1537  \n }\
1538  \n\
1539  \n if (l_firstValue)\
1540  \n {\
1541  \n l_firstValue = false;\
1542  \n }"
1543  );
1544  }
1545  else
1546  {
1547  shaderStr += std::string("\
1548  \n for (int i = 0; i < in_noOfComponents; ++i)\
1549  \n {\
1550  \n if (l_minValue[i] < scalar[i] || l_firstValue)\
1551  \n {\
1552  \n l_minValue[i] = scalar[i];\
1553  \n }\
1554  \n }\
1555  \n if (l_firstValue)\
1556  \n {\
1557  \n l_firstValue = false;\
1558  \n }"
1559  );
1560  }
1561  }
1562  else
1563  {
1564  shaderStr += std::string("\
1565  \n if (l_minValue.w > scalar.x || l_firstValue)\
1566  \n {\
1567  \n l_minValue.w = scalar.x;\
1568  \n }\
1569  \n\
1570  \n if (l_firstValue)\
1571  \n {\
1572  \n l_firstValue = false;\
1573  \n }"
1574  );
1575  }
1576  }
1578  {
1579  if (noOfComponents > 1 && independentComponents)
1580  {
1581  shaderStr += std::string("\
1582  \n for (int i = 0; i < in_noOfComponents; ++i)\
1583  \n {\
1584  \n // Get the intensity in volume scalar range\
1585  \n float intensity = in_scalarsRange[i][0] +\
1586  \n (in_scalarsRange[i][1] -\
1587  \n in_scalarsRange[i][0]) * scalar[i];\
1588  \n if (in_averageIPRange.x <= intensity &&\
1589  \n intensity <= in_averageIPRange.y)\
1590  \n {\
1591  \n l_avgValue[i] += computeOpacity(scalar, i) * scalar[i];\
1592  \n ++l_numSamples[i];\
1593  \n }\
1594  \n }"
1595  );
1596  }
1597  else
1598  {
1599  shaderStr += std::string("\
1600  \n // Get the intensity in volume scalar range\
1601  \n float intensity = in_scalarsRange[0][0] +\
1602  \n (in_scalarsRange[0][1] -\
1603  \n in_scalarsRange[0][0]) * scalar.x;\
1604  \n if (in_averageIPRange.x <= intensity &&\
1605  \n intensity <= in_averageIPRange.y)\
1606  \n {\
1607  \n l_avgValue.x += computeOpacity(scalar) * scalar.x;\
1608  \n ++l_numSamples.x;\
1609  \n }"
1610  );
1611  }
1612  }
1613  else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
1614  {
1615  if (noOfComponents > 1 && independentComponents)
1616  {
1617  shaderStr += std::string("\
1618  \n for (int i = 0; i < in_noOfComponents; ++i)\
1619  \n {\
1620  \n float opacity = computeOpacity(scalar, i);\
1621  \n l_sumValue[i] = l_sumValue[i] + opacity * scalar[i];\
1622  \n }"
1623  );
1624  }
1625  else
1626  {
1627  shaderStr += std::string("\
1628  \n float opacity = computeOpacity(scalar);\
1629  \n l_sumValue.x = l_sumValue.x + opacity * scalar.x;"
1630  );
1631  }
1632  }
1633  else if (mapper->GetBlendMode() == vtkVolumeMapper::ISOSURFACE_BLEND)
1634  {
1635  shaderStr += std::string("\
1636  \n#if NUMBER_OF_CONTOURS\
1637  \n int maxComp = 0;");
1638 
1639  std::string compParamStr = "";
1640  if (noOfComponents > 1 && independentComponents)
1641  {
1642  shaderStr += std::string("\
1643  \n for (int i = 1; i < in_noOfComponents; ++i)\
1644  \n {\
1645  \n if (in_componentWeight[i] > in_componentWeight[maxComp])\
1646  \n maxComp = i;\
1647  \n }");
1648  compParamStr = ", maxComp";
1649  }
1650  shaderStr += std::string("\
1651  \n if (g_currentT == 0)\
1652  \n {\
1653  \n l_initialIndex = findIsoSurfaceIndex(scalar[maxComp], l_normValues);\
1654  \n }\
1655  \n else\
1656  \n {\
1657  \n float s;\
1658  \n bool shade = false;\
1659  \n l_initialIndex = clamp(l_initialIndex, 0, NUMBER_OF_CONTOURS);\
1660  \n if (scalar[maxComp] < l_normValues[l_initialIndex])\
1661  \n {\
1662  \n s = l_normValues[l_initialIndex];\
1663  \n l_initialIndex--;\
1664  \n shade = true;\
1665  \n }\
1666  \n if (scalar[maxComp] > l_normValues[l_initialIndex+1])\
1667  \n {\
1668  \n s = l_normValues[l_initialIndex+1];\
1669  \n l_initialIndex++;\
1670  \n shade = true;\
1671  \n }\
1672  \n if (shade == true)\
1673  \n {\
1674  \n vec4 vs = vec4(s);\
1675  \n g_srcColor.a = computeOpacity(vs "+compParamStr+");\
1676  \n g_srcColor = computeColor(vs, g_srcColor.a "+compParamStr+");\
1677  \n g_srcColor.rgb *= g_srcColor.a;\
1678  \n g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;\
1679  \n }\
1680  \n }\
1681  \n#endif");
1682  }
1683  else if (mapper->GetBlendMode() == vtkVolumeMapper::COMPOSITE_BLEND)
1684  {
1685  if (noOfComponents > 1 && independentComponents)
1686  {
1687  shaderStr += std::string("\
1688  \n vec4 color[4]; vec4 tmp = vec4(0.0);\
1689  \n float totalAlpha = 0.0;\
1690  \n for (int i = 0; i < in_noOfComponents; ++i)\
1691  \n {\
1692  ");
1693  if (glMapper->GetUseDepthPass() && glMapper->GetCurrentPass() ==
1695  {
1696  shaderStr += std::string("\
1697  \n // Data fetching from the red channel of volume texture\
1698  \n float opacity = computeOpacity(scalar, i);\
1699  \n if (opacity > 0.0)\
1700  \n {\
1701  \n g_srcColor.a = opacity;\
1702  \n }\
1703  \n }"
1704  );
1705  }
1706  else if (!mask || !maskInput ||
1708  {
1709  shaderStr += std::string("\
1710  \n // Data fetching from the red channel of volume texture\
1711  \n color[i][3] = computeOpacity(scalar, i);\
1712  \n color[i] = computeColor(scalar, color[i][3], i);\
1713  \n totalAlpha += color[i][3] * in_componentWeight[i];\
1714  \n }\
1715  \n if (totalAlpha > 0.0)\
1716  \n {\
1717  \n for (int i = 0; i < in_noOfComponents; ++i)\
1718  \n {\
1719  \n // Only let visible components contribute to the final color\
1720  \n if (in_componentWeight[i] <= 0) continue;\
1721  \n\
1722  \n tmp.x += color[i].x * color[i].w * in_componentWeight[i];\
1723  \n tmp.y += color[i].y * color[i].w * in_componentWeight[i];\
1724  \n tmp.z += color[i].z * color[i].w * in_componentWeight[i];\
1725  \n tmp.w += ((color[i].w * color[i].w)/totalAlpha);\
1726  \n }\
1727  \n }\
1728  \n g_fragColor = (1.0f - g_fragColor.a) * tmp + g_fragColor;"
1729  );
1730  }
1731  }
1732  else if (glMapper->GetUseDepthPass() && glMapper->GetCurrentPass() ==
1734  {
1735  shaderStr += std::string("\
1736  \n g_srcColor = vec4(0.0);\
1737  \n g_srcColor.a = computeOpacity(scalar);"
1738  );
1739  }
1740  else
1741  {
1742  if (!mask || !maskInput ||
1744  {
1745  shaderStr += std::string("\
1746  \n g_srcColor = vec4(0.0);\
1747  \n g_srcColor.a = computeOpacity(scalar);\
1748  \n if (g_srcColor.a > 0.0)\
1749  \n {\
1750  \n g_srcColor = computeColor(scalar, g_srcColor.a);"
1751  );
1752  }
1753 
1754  shaderStr += std::string("\
1755  \n // Opacity calculation using compositing:\
1756  \n // Here we use front to back compositing scheme whereby\
1757  \n // the current sample value is multiplied to the\
1758  \n // currently accumulated alpha and then this product\
1759  \n // is subtracted from the sample value to get the\
1760  \n // alpha from the previous steps. Next, this alpha is\
1761  \n // multiplied with the current sample colour\
1762  \n // and accumulated to the composited colour. The alpha\
1763  \n // value from the previous steps is then accumulated\
1764  \n // to the composited colour alpha.\
1765  \n g_srcColor.rgb *= g_srcColor.a;\
1766  \n g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;"
1767  );
1768 
1769  if (!mask || !maskInput ||
1771  {
1772  shaderStr += std::string("\
1773  \n }"
1774  );
1775  }
1776  }
1777  }
1778  else
1779  {
1780  shaderStr += std::string();
1781  }
1782 
1783  shaderStr += std::string("\
1784  \n }"
1785  );
1786  return shaderStr;
1787  }
1788 
1789  //--------------------------------------------------------------------------
1791  vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
1792  {
1793  return std::string("\
1794  \n // Special coloring mode which renders the Prop Id in fragments that\
1795  \n // have accumulated certain level of opacity. Used during the selection\
1796  \n // pass vtkHardwareSelection::ACTOR_PASS.\
1797  \n if (g_fragColor.a > 3.0/ 255.0)\
1798  \n {\
1799  \n gl_FragData[0] = vec4(in_propId, 1.0);\
1800  \n }\
1801  \n else\
1802  \n {\
1803  \n gl_FragData[0] = vec4(0.0);\
1804  \n }\
1805  \n return;");
1806  };
1807 
1808  //--------------------------------------------------------------------------
1810  vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
1811  {
1812  return std::string("\
1813  \n // Special coloring mode which renders the voxel index in fragments that\
1814  \n // have accumulated certain level of opacity. Used during the selection\
1815  \n // pass vtkHardwareSelection::ID_LOW24.\
1816  \n if (g_fragColor.a > 3.0/ 255.0)\
1817  \n {\
1818  \n uvec3 volumeDim = uvec3(in_textureExtentsMax - in_textureExtentsMin);\
1819  \n uvec3 voxelCoords = uvec3(volumeDim * g_dataPos);\
1820  \n // vtkHardwareSelector assumes index 0 to be empty space, so add uint(1).\
1821  \n uint idx = volumeDim.x * volumeDim.y * voxelCoords.z +\
1822  \n volumeDim.x * voxelCoords.y + voxelCoords.x + uint(1);\
1823  \n gl_FragData[0] = vec4(float(idx % uint(256)) / 255.0,\
1824  \n float((idx / uint(256)) % uint(256)) / 255.0,\
1825  \n float((idx / uint(65536)) % uint(256)) / 255.0, 1.0);\
1826  \n }\
1827  \n else\
1828  \n {\
1829  \n gl_FragData[0] = vec4(0.0);\
1830  \n }\
1831  \n return;");
1832  };
1833 
1834  //--------------------------------------------------------------------------
1836  vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
1837  {
1838  return std::string("\
1839  \n // Special coloring mode which renders the voxel index in fragments that\
1840  \n // have accumulated certain level of opacity. Used during the selection\
1841  \n // pass vtkHardwareSelection::ID_MID24.\
1842  \n if (g_fragColor.a > 3.0/ 255.0)\
1843  \n {\
1844  \n uvec3 volumeDim = uvec3(in_textureExtentsMax - in_textureExtentsMin);\
1845  \n uvec3 voxelCoords = uvec3(volumeDim * g_dataPos);\
1846  \n // vtkHardwareSelector assumes index 0 to be empty space, so add uint(1).\
1847  \n uint idx = volumeDim.x * volumeDim.y * voxelCoords.z +\
1848  \n volumeDim.x * voxelCoords.y + voxelCoords.x + uint(1);\
1849  \n idx = ((idx & 0xff000000) >> 24);\
1850  \n gl_FragData[0] = vec4(float(idx % uint(256)) / 255.0,\
1851  \n float((idx / uint(256)) % uint(256)) / 255.0,\
1852  \n float(idx / uint(65536)) / 255.0, 1.0);\
1853  \n }\
1854  \n else\
1855  \n {\
1856  \n gl_FragData[0] = vec4(0.0);\
1857  \n }\
1858  \n return;");
1859  };
1860 
1861  //--------------------------------------------------------------------------
1863  vtkVolumeMapper* mapper,
1864  vtkVolume* vtkNotUsed(vol),
1865  int noOfComponents,
1866  int independentComponents = 0)
1867  {
1870 
1871  if (glMapper->GetUseDepthPass() && glMapper->GetCurrentPass() ==
1874  {
1875  return std::string();
1876  }
1878  {
1879  if (noOfComponents > 1 && independentComponents)
1880  {
1881  return std::string("\
1882  \n g_srcColor = vec4(0);\
1883  \n for (int i = 0; i < in_noOfComponents; ++i)\
1884  \n {\
1885  \n vec4 tmp = computeColor(l_maxValue, computeOpacity(l_maxValue, i), i);\
1886  \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
1887  \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
1888  \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
1889  \n g_srcColor[3] += tmp[3] * in_componentWeight[i];\
1890  \n }\
1891  \n g_fragColor = g_srcColor;"
1892  );
1893  }
1894  else
1895  {
1896  return std::string("\
1897  \n g_srcColor = computeColor(l_maxValue,\
1898  \n computeOpacity(l_maxValue));\
1899  \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
1900  \n g_fragColor.a = g_srcColor.a;"
1901  );
1902  }
1903  }
1905  {
1906  if (noOfComponents > 1 && independentComponents)
1907  {
1908  return std::string("\
1909  \n g_srcColor = vec4(0);\
1910  \n for (int i = 0; i < in_noOfComponents; ++i)\
1911  \n {\
1912  \n vec4 tmp = computeColor(l_minValue, computeOpacity(l_minValue, i), i);\
1913  \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
1914  \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
1915  \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
1916  \n g_srcColor[2] += tmp[3] * tmp[3] * in_componentWeight[i];\
1917  \n }\
1918  \n g_fragColor = g_srcColor;"
1919  );
1920  }
1921  else
1922  {
1923  return std::string("\
1924  \n g_srcColor = computeColor(l_minValue,\
1925  \n computeOpacity(l_minValue));\
1926  \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
1927  \n g_fragColor.a = g_srcColor.a;"
1928  );
1929  }
1930  }
1932  {
1933  if (noOfComponents > 1 && independentComponents)
1934  {
1935  return std::string("\
1936  \n for (int i = 0; i < in_noOfComponents; ++i)\
1937  \n {\
1938  \n if (l_numSamples[i] == uint(0))\
1939  \n {\
1940  \n continue;\
1941  \n }\
1942  \n l_avgValue[i] = l_avgValue[i] * in_componentWeight[i] /\
1943  \n l_numSamples[i];\
1944  \n if (i > 0)\
1945  \n {\
1946  \n l_avgValue[0] += l_avgValue[i];\
1947  \n }\
1948  \n }\
1949  \n l_avgValue[0] = clamp(l_avgValue[0], 0.0, 1.0);\
1950  \n g_fragColor = vec4(vec3(l_avgValue[0]), 1.0);"
1951  );
1952  }
1953  else
1954  {
1955  return std::string("\
1956  \n if (l_numSamples.x == uint(0))\
1957  \n {\
1958  \n discard;\
1959  \n }\
1960  \n else\
1961  \n {\
1962  \n l_avgValue.x /= l_numSamples.x;\
1963  \n l_avgValue.x = clamp(l_avgValue.x, 0.0, 1.0);\
1964  \n g_fragColor = vec4(vec3(l_avgValue.x), 1.0);\
1965  \n }"
1966  );
1967  }
1968  }
1969  else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
1970  {
1971  if (noOfComponents > 1 && independentComponents)
1972  {
1973  // Add all the components to get final color
1974  return std::string("\
1975  \n l_sumValue.x *= in_componentWeight.x;\
1976  \n for (int i = 1; i < in_noOfComponents; ++i)\
1977  \n {\
1978  \n l_sumValue.x += l_sumValue[i] * in_componentWeight[i];\
1979  \n }\
1980  \n l_sumValue.x = clamp(l_sumValue.x, 0.0, 1.0);\
1981  \n g_fragColor = vec4(vec3(l_sumValue.x), 1.0);"
1982  );
1983  }
1984  else
1985  {
1986  return std::string("\
1987  \n l_sumValue.x = clamp(l_sumValue.x, 0.0, 1.0);\
1988  \n g_fragColor = vec4(vec3(l_sumValue.x), 1.0);"
1989  );
1990  }
1991  }
1992  else
1993  {
1994  return std::string();
1995  }
1996  }
1997 
1998  //--------------------------------------------------------------------------
2000  vtkVolumeMapper* vtkNotUsed(mapper),
2001  vtkVolume* vtkNotUsed(vol))
2002  {
2003  return std::string();
2004  }
2005 
2006  //--------------------------------------------------------------------------
2008  vtkVolumeMapper* vtkNotUsed(mapper),
2009  vtkVolume* vtkNotUsed(vol))
2010  {
2011  return std::string("\
2012  \n const float g_opacityThreshold = 1.0 - 1.0 / 255.0;");
2013  }
2014 
2015  //--------------------------------------------------------------------------
2017  vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2018  {
2019  return std::string("\
2020  \n uniform vec3 in_propId;");
2021  };
2022 
2023  //--------------------------------------------------------------------------
2025  vtkVolumeMapper* vtkNotUsed(mapper),
2026  vtkVolume* vtkNotUsed(vol))
2027  {
2028  return std::string("\
2029  \n // Flag to indicate if the raymarch loop should terminate \
2030  \n bool stop = false;\
2031  \n\
2032  \n g_terminatePointMax = 0.0;\
2033  \n\
2034  \n#ifdef GL_ES\
2035  \n vec4 l_depthValue = vec4(1.0,1.0,1.0,1.0);\
2036  \n#else\
2037  \n vec4 l_depthValue = texture2D(in_depthSampler, fragTexCoord);\
2038  \n#endif\
2039  \n // Depth test\
2040  \n if(gl_FragCoord.z >= l_depthValue.x)\
2041  \n {\
2042  \n discard;\
2043  \n }\
2044  \n\
2045  \n // color buffer or max scalar buffer have a reduced size.\
2046  \n fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
2047  \n in_inverseOriginalWindowSize;\
2048  \n\
2049  \n // Compute max number of iterations it will take before we hit\
2050  \n // the termination point\
2051  \n\
2052  \n // Abscissa of the point on the depth buffer along the ray.\
2053  \n // point in texture coordinates\
2054  \n vec4 terminatePoint = WindowToNDC(gl_FragCoord.x, gl_FragCoord.y, l_depthValue.x);\
2055  \n\
2056  \n // From normalized device coordinates to eye coordinates.\
2057  \n // in_projectionMatrix is inversed because of way VT\
2058  \n // From eye coordinates to texture coordinates\
2059  \n terminatePoint = ip_inverseTextureDataAdjusted *\
2060  \n in_inverseVolumeMatrix[0] *\
2061  \n in_inverseModelViewMatrix *\
2062  \n in_inverseProjectionMatrix *\
2063  \n terminatePoint;\
2064  \n terminatePoint /= terminatePoint.w;\
2065  \n\
2066  \n g_terminatePointMax = length(terminatePoint.xyz - g_dataPos.xyz) /\
2067  \n length(g_dirStep);\
2068  \n g_currentT = 0.0;");
2069  }
2070 
2071  //--------------------------------------------------------------------------
2073  vtkVolumeMapper* vtkNotUsed(mapper),
2074  vtkVolume* vtkNotUsed(vol))
2075  {
2076  return std::string("\
2077  \n if(any(greaterThan(g_dataPos, in_texMax[0])) ||\
2078  \n any(lessThan(g_dataPos, in_texMin[0])))\
2079  \n {\
2080  \n break;\
2081  \n }\
2082  \n\
2083  \n // Early ray termination\
2084  \n // if the currently composited colour alpha is already fully saturated\
2085  \n // we terminated the loop or if we have hit an obstacle in the\
2086  \n // direction of they ray (using depth buffer) we terminate as well.\
2087  \n if((g_fragColor.a > g_opacityThreshold) || \
2088  \n g_currentT >= g_terminatePointMax)\
2089  \n {\
2090  \n break;\
2091  \n }\
2092  \n ++g_currentT;"
2093  );
2094  }
2095 
2096  //--------------------------------------------------------------------------
2098  vtkVolumeMapper* vtkNotUsed(mapper),
2099  vtkVolume* vtkNotUsed(vol))
2100  {
2101  return std::string();
2102  }
2103 
2104  //--------------------------------------------------------------------------
2106  vtkVolumeMapper* vtkNotUsed(mapper),
2107  vtkVolume* vtkNotUsed(vol))
2108  {
2109  return std::string();
2110  }
2111 
2112  //--------------------------------------------------------------------------
2114  vtkVolumeMapper* mapper,
2115  vtkVolume* vtkNotUsed(vol))
2116  {
2117  if (!mapper->GetCropping()) {
2118  return std::string();
2119  }
2120 
2121  return std::string("\
2122  \nuniform float in_croppingPlanes[6];\
2123  \nuniform int in_croppingFlags [32];\
2124  \nfloat croppingPlanesTexture[6];\
2125  \n\
2126  \n// X: axis = 0, Y: axis = 1, Z: axis = 2\
2127  \n// cp Cropping plane bounds (minX, maxX, minY, maxY, minZ, maxZ)\
2128  \nint computeRegionCoord(float cp[6], vec3 pos, int axis)\
2129  \n {\
2130  \n int cpmin = axis * 2;\
2131  \n int cpmax = cpmin + 1;\
2132  \n\
2133  \n if (pos[axis] < cp[cpmin])\
2134  \n {\
2135  \n return 1;\
2136  \n }\
2137  \n else if (pos[axis] >= cp[cpmin] &&\
2138  \n pos[axis] < cp[cpmax])\
2139  \n {\
2140  \n return 2;\
2141  \n }\
2142  \n else if (pos[axis] >= cp[cpmax])\
2143  \n {\
2144  \n return 3;\
2145  \n }\
2146  \n return 0;\
2147  \n }\
2148  \n\
2149  \nint computeRegion(float cp[6], vec3 pos)\
2150  \n {\
2151  \n return (computeRegionCoord(cp, pos, 0) +\
2152  \n (computeRegionCoord(cp, pos, 1) - 1) * 3 +\
2153  \n (computeRegionCoord(cp, pos, 2) - 1) * 9);\
2154  \n }"
2155  );
2156  }
2157 
2158  //--------------------------------------------------------------------------
2160  vtkVolumeMapper* mapper,
2161  vtkVolume* vtkNotUsed(vol))
2162  {
2163  if (!mapper->GetCropping()) {
2164  return std::string();
2165  }
2166 
2167  return std::string("\
2168  \n // Convert cropping region to texture space\
2169  \n mat4 datasetToTextureMat = in_inverseTextureDatasetMatrix[0];\
2170  \n\
2171  \n vec4 tempCrop = vec4(in_croppingPlanes[0], 0.0, 0.0, 1.0);\
2172  \n tempCrop = datasetToTextureMat * tempCrop;\
2173  \n if (tempCrop[3] != 0.0)\
2174  \n {\
2175  \n tempCrop[0] /= tempCrop[3];\
2176  \n }\
2177  \n croppingPlanesTexture[0] = tempCrop[0];\
2178  \n\
2179  \n tempCrop = vec4(in_croppingPlanes[1], 0.0, 0.0, 1.0);\
2180  \n tempCrop = datasetToTextureMat * tempCrop;\
2181  \n if (tempCrop[3] != 0.0)\
2182  \n {\
2183  \n tempCrop[0] /= tempCrop[3];\
2184  \n }\
2185  \n croppingPlanesTexture[1] = tempCrop[0];\
2186  \n\
2187  \n tempCrop = vec4(0.0, in_croppingPlanes[2], 0.0, 1.0);\
2188  \n tempCrop = datasetToTextureMat * tempCrop;\
2189  \n if (tempCrop[3] != 0.0)\
2190  \n {\
2191  \n tempCrop[1] /= tempCrop[3];\
2192  \n }\
2193  \n croppingPlanesTexture[2] = tempCrop[1];\
2194  \n\
2195  \n tempCrop = vec4(0.0, in_croppingPlanes[3], 0.0, 1.0);\
2196  \n tempCrop = datasetToTextureMat * tempCrop;\
2197  \n if (tempCrop[3] != 0.0)\
2198  \n {\
2199  \n tempCrop[1] /= tempCrop[3];\
2200  \n }\
2201  \n croppingPlanesTexture[3] = tempCrop[1];\
2202  \n\
2203  \n tempCrop = vec4(0.0, 0.0, in_croppingPlanes[4], 1.0);\
2204  \n tempCrop = datasetToTextureMat * tempCrop;\
2205  \n if (tempCrop[3] != 0.0)\
2206  \n {\
2207  \n tempCrop[2] /= tempCrop[3];\
2208  \n }\
2209  \n croppingPlanesTexture[4] = tempCrop[2];\
2210  \n\
2211  \n tempCrop = vec4(0.0, 0.0, in_croppingPlanes[5], 1.0);\
2212  \n tempCrop = datasetToTextureMat * tempCrop;\
2213  \n if (tempCrop[3] != 0.0)\
2214  \n {\
2215  \n tempCrop[2] /= tempCrop[3];\
2216  \n }\
2217  \n croppingPlanesTexture[5] = tempCrop[2];"
2218  );
2219  }
2220 
2221  //--------------------------------------------------------------------------
2223  vtkVolumeMapper* mapper,
2224  vtkVolume* vtkNotUsed(vol))
2225  {
2226  if (!mapper->GetCropping()) {
2227  return std::string();
2228  }
2229 
2230  return std::string("\
2231  \n // Determine region\
2232  \n int regionNo = computeRegion(croppingPlanesTexture, g_dataPos);\
2233  \n\
2234  \n // Do & operation with cropping flags\
2235  \n // Pass the flag that its Ok to sample or not to sample\
2236  \n if (in_croppingFlags[regionNo] == 0)\
2237  \n {\
2238  \n // Skip this voxel\
2239  \n g_skip = true;\
2240  \n }"
2241  );
2242  }
2243 
2244  //--------------------------------------------------------------------------
2246  vtkVolumeMapper* vtkNotUsed(mapper),
2247  vtkVolume* vtkNotUsed(vol))
2248  {
2249  return std::string();
2250  }
2251 
2252  //--------------------------------------------------------------------------
2254  vtkVolumeMapper* vtkNotUsed(mapper),
2255  vtkVolume* vtkNotUsed(vol))
2256  {
2257  return std::string();
2258  }
2259 
2260  //--------------------------------------------------------------------------
2262  vtkVolumeMapper* vtkNotUsed(mapper),
2263  vtkVolume* vtkNotUsed(vol))
2264  {
2265  return std::string("\
2266  \n int clippingPlanesSize;\
2267  \n vec3 objRayDir;\
2268  \n mat4 textureToObjMat;");
2269  }
2270 
2271  //--------------------------------------------------------------------------
2273  vtkVolumeMapper* mapper,
2274  vtkVolume* vtkNotUsed(vol))
2275  {
2276  if (!mapper->GetClippingPlanes())
2277  {
2278  return std::string();
2279  }
2280 
2281  std::string shaderStr;
2282  if (!ren->GetActiveCamera()->GetParallelProjection())
2283  {
2284  shaderStr = std::string("\
2285  vec4 tempClip = in_volumeMatrix[0] * vec4(rayDir, 0.0);\
2286  \n if (tempClip.w != 0.0)\
2287  \n {\
2288  \n tempClip = tempClip/tempClip.w;\
2289  \n tempClip.w = 1.0;\
2290  \n }\
2291  \n objRayDir = tempClip.xyz;");
2292  }
2293  else
2294  {
2295  shaderStr = std::string("\
2296  objRayDir = normalize(in_projectionDirection);");
2297  }
2298 
2299  shaderStr += std::string("\
2300  \n clippingPlanesSize = int(in_clippingPlanes[0]);\
2301  \n vec4 objDataPos = vec4(0.0);\
2302  \n textureToObjMat = in_volumeMatrix[0] * in_textureDatasetMatrix[0];\
2303  \n\
2304  \n vec4 terminatePointObj = textureToObjMat * terminatePoint;\
2305  \n if (terminatePointObj.w != 0.0)\
2306  \n {\
2307  \n terminatePointObj = terminatePointObj/ terminatePointObj.w ;\
2308  \n terminatePointObj.w = 1.0;\
2309  \n }\
2310  \n\
2311  \n for (int i = 0; i < clippingPlanesSize; i = i + 6)\
2312  \n {\
2313  \n if (in_useJittering)\
2314  \n {\
2315  \n objDataPos = textureToObjMat * vec4(g_dataPos - g_rayJitter,\
2316  \n 1.0);\
2317  \n }\
2318  \n else\
2319  \n {\
2320  \n objDataPos = textureToObjMat * vec4(g_dataPos - g_dirStep, 1.0);\
2321  \n }\
2322  \n if (objDataPos.w != 0.0)\
2323  \n {\
2324  \n objDataPos = objDataPos/objDataPos.w; objDataPos.w = 1.0;\
2325  \n }\
2326  \n vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\
2327  \n in_clippingPlanes[i + 2],\
2328  \n in_clippingPlanes[i + 3]);\
2329  \n vec3 planeNormal = vec3(in_clippingPlanes[i + 4],\
2330  \n in_clippingPlanes[i + 5],\
2331  \n in_clippingPlanes[i + 6]);\
2332  \n vec3 normalizedPlaneNormal = normalize(planeNormal);\
2333  \n\
2334  \n float rayDotNormal = dot(objRayDir, normalizedPlaneNormal);\
2335  \n bool frontFace = rayDotNormal > 0;\
2336  \n float distance = dot(normalizedPlaneNormal, planeOrigin - objDataPos.xyz);\
2337  \n\
2338  \n if (frontFace && // Observing from the clipped side (plane's front face)\
2339  \n distance > 0.0) // Ray-entry lies on the clipped side.\
2340  \n {\
2341  \n // Scale the point-plane distance to the ray direction and update the\
2342  \n // entry point.\
2343  \n float rayScaledDist = distance / rayDotNormal;\
2344  \n vec4 newObjDataPos = vec4(objDataPos.xyz + rayScaledDist * objRayDir, 1.0);\
2345  \n newObjDataPos = in_inverseTextureDatasetMatrix[0]\
2346  \n * in_inverseVolumeMatrix[0] * vec4(newObjDataPos.xyz, 1.0);\
2347  \n if (newObjDataPos.w != 0.0)\
2348  \n {\
2349  \n newObjDataPos /= newObjDataPos.w;\
2350  \n }\
2351  \n if (in_useJittering)\
2352  \n {\
2353  \n g_dataPos = newObjDataPos.xyz + g_rayJitter;\
2354  \n }\
2355  \n else\
2356  \n {\
2357  \n g_dataPos = newObjDataPos.xyz + g_dirStep;\
2358  \n }\
2359  \n\
2360  \n bool stop = any(greaterThan(g_dataPos, in_texMax[0])) ||\
2361  \n any(lessThan(g_dataPos, in_texMin[0]));\
2362  \n if (stop)\
2363  \n {\
2364  \n // The ray exits the bounding box before ever intersecting the plane (only\
2365  \n // the clipped space is hit).\
2366  \n discard;\
2367  \n }\
2368  \n\
2369  \n bool behindGeometry = dot(terminatePointObj.xyz - planeOrigin.xyz, normalizedPlaneNormal) < 0.0;\
2370  \n if (behindGeometry)\
2371  \n {\
2372  \n // Geometry appears in front of the plane.\
2373  \n discard;\
2374  \n }\
2375  \n\
2376  \n // Update the number of ray marching steps to account for the clipped entry point (\
2377  \n // this is necessary in case the ray hits geometry after marching behind the plane,\
2378  \n // given that the number of steps was assumed to be from the not-clipped entry).\
2379  \n g_terminatePointMax = length(terminatePoint.xyz - g_dataPos.xyz) /\
2380  \n length(g_dirStep);\
2381  \n }\
2382  \n }");
2383 
2384  return shaderStr;
2385  }
2386 
2387  //--------------------------------------------------------------------------
2389  vtkVolumeMapper* mapper,
2390  vtkVolume* vtkNotUsed(vol))
2391  {
2392  if (!mapper->GetClippingPlanes())
2393  {
2394  return std::string();
2395  }
2396  else
2397  {
2398  return std::string("\
2399  \n for (int i = 0; i < clippingPlanesSize && !g_skip; i = i + 6)\
2400  \n {\
2401  \n vec4 objDataPos = textureToObjMat * vec4(g_dataPos, 1.0);\
2402  \n if (objDataPos.w != 0.0)\
2403  \n {\
2404  \n objDataPos /= objDataPos.w;\
2405  \n }\
2406  \n vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\
2407  \n in_clippingPlanes[i + 2],\
2408  \n in_clippingPlanes[i + 3]);\
2409  \n vec3 planeNormal = vec3(in_clippingPlanes[i + 4],\
2410  \n in_clippingPlanes[i + 5],\
2411  \n in_clippingPlanes[i + 6]);\
2412  \n if (dot(vec3(objDataPos.xyz - planeOrigin), planeNormal) < 0 && dot(objRayDir, planeNormal) < 0)\
2413  \n {\
2414  \n g_skip = true;\
2415  \n g_exit = true;\
2416  \n }\
2417  \n }"
2418  );
2419  }
2420  }
2421 
2422  //--------------------------------------------------------------------------
2424  vtkVolumeMapper* vtkNotUsed(mapper),
2425  vtkVolume* vtkNotUsed(vol))
2426  {
2427  return std::string();
2428  }
2429 
2430  //--------------------------------------------------------------------------
2432  vtkVolumeMapper* vtkNotUsed(mapper),
2433  vtkVolume* vtkNotUsed(vol),
2434  vtkImageData* maskInput,
2435  vtkVolumeTexture* mask,
2436  int vtkNotUsed(maskType))
2437  {
2438  if (!mask || !maskInput)
2439  {
2440  return std::string();
2441  }
2442  else
2443  {
2444  return std::string("uniform sampler3D in_mask;");
2445  }
2446  }
2447 
2448  //--------------------------------------------------------------------------
2450  vtkVolumeMapper* vtkNotUsed(mapper),
2451  vtkVolume* vtkNotUsed(vol),
2452  vtkImageData* maskInput,
2453  vtkVolumeTexture* mask,
2454  int maskType)
2455  {
2456  if (!mask || !maskInput ||
2458  {
2459  return std::string();
2460  }
2461  else
2462  {
2463  return std::string("\
2464  \nvec4 maskValue = texture3D(in_mask, g_dataPos);\
2465  \nif(maskValue.r <= 0.0)\
2466  \n {\
2467  \n g_skip = true;\
2468  \n }"
2469  );
2470  }
2471  }
2472 
2473  //--------------------------------------------------------------------------
2475  vtkVolumeMapper* vtkNotUsed(mapper),
2476  vtkVolume* vtkNotUsed(vol),
2477  vtkImageData* maskInput,
2478  vtkVolumeTexture* mask,
2479  int maskType)
2480  {
2481  if (!mask || !maskInput ||
2483  {
2484  return std::string();
2485  }
2486  else
2487  {
2488  return std::string("\
2489  \nuniform float in_maskBlendFactor;\
2490  \nuniform sampler2D in_mask1;\
2491  \nuniform sampler2D in_mask2;"
2492  );
2493  }
2494  }
2495 
2496  //--------------------------------------------------------------------------
2498  vtkVolumeMapper* vtkNotUsed(mapper),
2499  vtkVolume* vtkNotUsed(vol),
2500  vtkImageData* maskInput,
2501  vtkVolumeTexture* mask,
2502  int maskType,
2503  int noOfComponents)
2504  {
2505  if (!mask || !maskInput ||
2507  {
2508  return std::string();
2509  }
2510  else
2511  {
2512  std::string shaderStr = std::string("\
2513  \nvec4 scalar = texture3D(in_volume[0], g_dataPos);");
2514 
2515  // simulate old intensity textures
2516  if (noOfComponents == 1)
2517  {
2518  shaderStr += std::string("\
2519  \n scalar.r = scalar.r * in_volume_scale[0].r + in_volume_bias[0].r;\
2520  \n scalar = vec4(scalar.r);"
2521  );
2522  }
2523  else
2524  {
2525  // handle bias and scale
2526  shaderStr += std::string("\
2527  \n scalar = scalar * in_volume_scale[0] + in_volume_bias[0];"
2528  );
2529  }
2530 
2531  return shaderStr + std::string("\
2532  \nif (in_maskBlendFactor == 0.0)\
2533  \n {\
2534  \n g_srcColor = computeColor(scalar, computeOpacity(scalar));\
2535  \n }\
2536  \nelse\
2537  \n {\
2538  \n float opacity = computeOpacity(scalar);\
2539  \n // Get the mask value at this same location\
2540  \n vec4 maskValue = texture3D(in_mask, g_dataPos);\
2541  \n if(maskValue.r == 0.0)\
2542  \n {\
2543  \n g_srcColor = computeColor(scalar, opacity);\
2544  \n }\
2545  \n else\
2546  \n {\
2547  \n if (maskValue.r == 1.0/255.0)\
2548  \n {\
2549  \n g_srcColor = texture2D(in_mask1, vec2(scalar.w,0.0));\
2550  \n }\
2551  \n else\
2552  \n {\
2553  \n // maskValue.r == 2.0/255.0\
2554  \n g_srcColor = texture2D(in_mask2, vec2(scalar.w,0.0));\
2555  \n }\
2556  \n g_srcColor.a = 1.0;\
2557  \n if(in_maskBlendFactor < 1.0)\
2558  \n {\
2559  \n g_srcColor = (1.0 - in_maskBlendFactor) *\
2560  \n computeColor(scalar, opacity) +\
2561  \n in_maskBlendFactor * g_srcColor;\
2562  \n }\
2563  \n }\
2564  \n g_srcColor.a = opacity;\
2565  \n }"
2566  );
2567  }
2568  }
2569 
2570  //--------------------------------------------------------------------------
2572  vtkVolumeMapper* vtkNotUsed(mapper),
2573  vtkVolume* vtkNotUsed(vol))
2574  {
2575  return std::string(
2576  "uniform bool in_clampDepthToBackface;\n"
2577  "vec3 l_opaqueFragPos;\n"
2578  "bool l_updateDepth;\n");
2579  }
2580 
2581  //--------------------------------------------------------------------------
2583  vtkVolumeMapper* vtkNotUsed(mapper),
2584  vtkVolume* vtkNotUsed(vol))
2585  {
2586  return std::string("\
2587  \n l_opaqueFragPos = vec3(-1.0);\
2588  \n if(in_clampDepthToBackface)\
2589  \n {\
2590  \n l_opaqueFragPos = g_dataPos;\
2591  \n }\
2592  \n l_updateDepth = true;"
2593  );
2594  }
2595 
2596  //--------------------------------------------------------------------------
2598  vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper),
2599  vtkVolume* vtkNotUsed(vol))
2600  {
2601  return std::string("\
2602  \n if(!g_skip && g_srcColor.a > 0.0 && l_updateDepth)\
2603  \n {\
2604  \n l_opaqueFragPos = g_dataPos;\
2605  \n l_updateDepth = false;\
2606  \n }"
2607  );
2608  }
2609 
2610  //--------------------------------------------------------------------------
2612  vtkVolumeMapper* vtkNotUsed(mapper),
2613  vtkVolume* vtkNotUsed(vol))
2614  {
2615  return std::string("\
2616  \n if (l_opaqueFragPos == vec3(-1.0))\
2617  \n {\
2618  \n gl_FragData[1] = vec4(1.0);\
2619  \n }\
2620  \n else\
2621  \n {\
2622  \n vec4 depthValue = in_projectionMatrix * in_modelViewMatrix *\
2623  \n in_volumeMatrix[0] * in_textureDatasetMatrix[0] *\
2624  \n vec4(l_opaqueFragPos, 1.0);\
2625  \n depthValue /= depthValue.w;\
2626  \n gl_FragData[1] = vec4(vec3(0.5 * (gl_DepthRange.far -\
2627  \n gl_DepthRange.near) * depthValue.z + 0.5 *\
2628  \n (gl_DepthRange.far + gl_DepthRange.near)), 1.0);\
2629  \n }"
2630  );
2631  }
2632 
2633  //--------------------------------------------------------------------------
2635  vtkVolumeMapper* vtkNotUsed(mapper),
2636  vtkVolume* vtkNotUsed(vol))
2637  {
2638  return std::string("\
2639  \n vec3 l_isoPos = g_dataPos;"
2640  );
2641  }
2642 
2643  //--------------------------------------------------------------------------
2645  vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper),
2646  vtkVolume* vtkNotUsed(vol))
2647  {
2648  return std::string("\
2649  \n if(!g_skip && g_srcColor.a > 0.0)\
2650  \n {\
2651  \n l_isoPos = g_dataPos;\
2652  \n g_exit = true; g_skip = true;\
2653  \n }"
2654  );
2655  }
2656 
2657  //--------------------------------------------------------------------------
2659  vtkVolumeMapper* vtkNotUsed(mapper),
2660  vtkVolume* vtkNotUsed(vol))
2661  {
2662  return std::string("\
2663  \n vec4 depthValue = in_projectionMatrix * in_modelViewMatrix *\
2664  \n in_volumeMatrix[0] * in_textureDatasetMatrix[0] *\
2665  \n vec4(l_isoPos, 1.0);\
2666  \n gl_FragData[0] = vec4(l_isoPos, 1.0);\
2667  \n gl_FragData[1] = vec4(vec3((depthValue.z/depthValue.w) * 0.5 + 0.5),\
2668  \n 1.0);"
2669  );
2670  }
2671 
2672  //---------------------------------------------------------------------------
2674  vtkVolumeMapper* vtkNotUsed(mapper),
2675  vtkVolume* vtkNotUsed(vol))
2676  {
2677  return std::string("\
2678  \n initializeRayCast();\
2679  \n castRay(-1.0, -1.0);\
2680  \n finalizeRayCast();");
2681  }
2682 
2683  //---------------------------------------------------------------------------
2684  std::string ImageSampleDeclarationFrag(const std::vector<std::string>& varNames,
2685  const size_t usedNames)
2686  {
2687  std::string shader = "\n";
2688  for (size_t i = 0; i < usedNames; i++)
2689  {
2690  shader += "uniform sampler2D " + varNames[i] + ";\n";
2691  }
2692  return shader;
2693  }
2694 
2695  //---------------------------------------------------------------------------
2696  std::string ImageSampleImplementationFrag(const std::vector<std::string>& varNames,
2697  const size_t usedNames)
2698  {
2699  std::string shader = "\n";
2700  for (size_t i = 0; i < usedNames; i++)
2701  {
2702  std::stringstream ss; ss << i;
2703  shader += " gl_FragData[" + ss.str() + "] = texture2D("+ varNames[i] +
2704  ", texCoord);\n";
2705  }
2706  shader += " return;\n";
2707  return shader;
2708  }
2709 }
2710 
2711 #endif // vtkVolumeShaderComposer_h
2712 // VTK-HeaderTest-Exclude: vtkVolumeShaderComposer.h
std::string ShadingExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents=0)
std::string RenderToImageImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string BaseImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
represents a volume (data & properties) in a rendered scene
Definition: vtkVolume.h:44
std::string BaseInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int lightingComplexity)
std::string CroppingDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string PreComputeGradientsImpl(vtkRenderer *vtkNotUsed(ren), vtkVolume *vtkNotUsed(vol), int noOfComponents=1, int independentComponents=0)
Abstract class for a volume mapper.
std::string ComputeGradientOpacityMulti1DDecl(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string DepthPassInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
virtual int GetBlendMode()
Set/Get the blend mode.
std::string ComputeColorMultiDeclaration(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
Creates and manages the volume texture rendered by vtkOpenGLGPUVolumeRayCastMapper.
std::map< int, vtkVolumeInputHelper > VolumeInputMap
std::string PickingActorPassDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string CompositeMaskImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType, int noOfComponents)
std::string RenderToImageDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ShadingSingleInput(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType, int noOfComponents, int independentComponents=0)
virtual vtkVolumeProperty * GetProperty()
Set/Get the volume property.
std::string ComputeGradientOpacity1DDecl(vtkVolume *vol, int noOfComponents, int independentComponents, std::map< int, std::string > gradientTableMap)
std::string RenderToImageExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
abstract specification for renderers
Definition: vtkRenderer.h:57
std::string CroppingDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string TerminationExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ShadingDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string BaseDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), bool multipleInputs)
virtual vtkPlaneCollection * GetClippingPlanes()
Get/Set the vtkPlaneCollection which specifies the clipping planes.
virtual int GetTransferFunctionMode()
Color-opacity transfer function mode.
vtkCamera * GetActiveCamera()
Get the current camera.
int GetShade(int index)
Set/Get the shading of a volume.
std::string PickingActorPassExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ClippingImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string ComputeLightingDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents, int vtkNotUsed(numberOfLights), int lightingComplexity)
OpenGL implementation of volume rendering through ray-casting.
static vtkOpenGLGPUVolumeRayCastMapper * SafeDownCast(vtkObjectBase *o)
std::string TerminationInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string CroppingImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string TerminationImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ClippingDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string CompositeMaskDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType)
std::string ClippingExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
topologically and geometrically regular array of data
Definition: vtkImageData.h:39
bool HasGradientOpacity(int index=0)
Check whether or not we have the gradient opacity.
std::string ComputeColor2DDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, std::map< int, std::string > colorTableMap)
std::string ComputeGradientDeclaration(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
static vtkGPUVolumeRayCastMapper * SafeDownCast(vtkObjectBase *o)
std::string WorkerImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ImageSampleImplementationFrag(const std::vector< std::string > &varNames, const size_t usedNames)
std::string ComputeClipPositionImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ComputeOpacity2DDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, std::map< int, std::string > opacityTableMap)
std::string ComputeRayDirectionDeclaration(vtkRenderer *ren, vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int vtkNotUsed(noOfComponents))
std::string GradientCacheDec(vtkRenderer *vtkNotUsed(ren), vtkVolume *vtkNotUsed(vol), vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int independentComponents=0)
std::string ShadingInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
represents the common properties for rendering a volume.
virtual vtkTypeBool GetCropping()
Turn On/Off orthogonal cropping.
std::string ShadingDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string CroppingExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ClippingInit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string ClippingDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string Transfer2DDeclaration(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string ComputeTextureCoordinates(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string BinaryMaskImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType)
std::string BaseDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int vtkNotUsed(numberOfLights), int lightingComplexity, int noOfComponents, int independentComponents)
std::string ComputeOpacityMultiDeclaration(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string PickingIdLow24PassExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string CroppingInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string ImageSampleDeclarationFrag(const std::vector< std::string > &varNames, const size_t usedNames)
std::string BinaryMaskDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeTexture *mask, int vtkNotUsed(maskType))
virtual vtkTypeBool GetParallelProjection()
Set/Get the value of the ParallelProjection instance variable.
virtual vtkTypeBool GetUseDepthPass()
If UseDepthPass is on, the mapper will use two passes.
std::string ShadingMultipleInputs(vtkVolumeMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string TerminationDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string DepthPassExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string DepthPassImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string BaseExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string TerminationDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ComputeOpacityDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, std::map< int, std::string > opacityTableMap)
std::string ComputeColorDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, std::map< int, std::string > colorTableMap)
std::string RenderToImageInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string PickingIdMid24PassExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))