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 
19 #include "vtkVolumeMask.h"
20 
21 #include <vtkCamera.h>
23 #include <vtkRenderer.h>
24 #include <vtkVolume.h>
25 #include <vtkVolumeMapper.h>
26 #include <vtkVolumeProperty.h>
27 
28 #include <map>
29 #include <sstream>
30 #include <string>
31 
32 // NOTE:
33 // In this code, we referred to various spaces described below:
34 // Object space: Raw coordinates in space defined by volume matrix
35 // Dataset space: Raw coordinates
36 // Eye space: Coordinates in eye space (as referred in computer graphics)
37 
38 namespace vtkvolume
39 {
40  //--------------------------------------------------------------------------
42  const std::string &replace, bool all)
43  {
44  if (replace.empty())
45  {
46  return source;
47  }
48 
49  std::string::size_type pos = 0;
50  bool first = true;
51  while ((pos = source.find(search, 0)) != std::string::npos)
52  {
53  source.replace(pos, search.length(), replace);
54  pos += search.length();
55  if (first)
56  {
57  first = false;
58  if (!all)
59  {
60  return source;
61  }
62  }
63  }
64  return source;
65  }
66 
67  //--------------------------------------------------------------------------
69  vtkVolumeMapper* vtkNotUsed(mapper),
70  vtkVolume* vtkNotUsed(vol))
71  {
72  return std::string("\
73  \n vec4 pos = in_projectionMatrix * in_modelViewMatrix *\
74  \n in_volumeMatrix * vec4(in_vertexPos.xyz, 1.0);\
75  \n gl_Position = pos;"
76  );
77  }
78 
79  //--------------------------------------------------------------------------
81  vtkVolumeMapper* vtkNotUsed(mapper),
82  vtkVolume* vtkNotUsed(vol))
83  {
84  return std::string(
85  "\n // For point dataset, we offset the texture coordinate\
86  \n // to account for OpenGL treating voxel at the center of the cell.\
87  \n vec3 uvx = sign(in_cellSpacing) * (in_vertexPos - in_volumeExtentsMin) /\
88  \n (in_volumeExtentsMax - in_volumeExtentsMin);\
89  \n\
90  \n if (in_cellFlag)\
91  \n {\
92  \n ip_textureCoords = uvx;\
93  \n ip_inverseTextureDataAdjusted = in_inverseTextureDatasetMatrix;\
94  \n }\
95  \n else\
96  \n {\
97  \n // Transform cell tex-coordinates to point tex-coordinates\
98  \n ip_textureCoords = (in_cellToPoint * vec4(uvx, 1.0)).xyz;\
99  \n ip_inverseTextureDataAdjusted = in_cellToPoint * in_inverseTextureDatasetMatrix;\
100  \n }");
101  }
102 
103  //--------------------------------------------------------------------------
105  vtkVolumeMapper* vtkNotUsed(mapper),
106  vtkVolume* vtkNotUsed(vol))
107  {
108  return std::string("\
109  \n uniform bool in_cellFlag;\
110  \n uniform vec3 in_cellSpacing;\
111  \n uniform mat4 in_modelViewMatrix;\
112  \n uniform mat4 in_projectionMatrix;\
113  \n uniform mat4 in_volumeMatrix;\
114  \n\
115  \n uniform vec3 in_volumeExtentsMin;\
116  \n uniform vec3 in_volumeExtentsMax;\
117  \n\
118  \n uniform mat4 in_inverseTextureDatasetMatrix;\
119  \n uniform mat4 in_cellToPoint;\
120  \n uniform vec3 in_textureExtentsMax;\
121  \n uniform vec3 in_textureExtentsMin;\
122  \n\
123  \n //This variable could be 'invariant varying' but it is declared\
124  \n //as 'varying' to avoid compiler compatibility issues.\
125  \n varying mat4 ip_inverseTextureDataAdjusted;");
126  }
127 
128  //--------------------------------------------------------------------------
130  vtkVolumeMapper* mapper,
131  vtkVolume* vtkNotUsed(vol),
132  int vtkNotUsed(numberOfLights),
133  int lightingComplexity,
134  bool hasGradientOpacity,
135  int noOfComponents,
136  int independentComponents)
137  {
138  std::string shaderStr = std::string("\
139  \n// Volume dataset\
140  \nuniform sampler3D in_volume;\
141  \nuniform int in_noOfComponents;\
142  \nuniform int in_independentComponents;\
143  \n\
144  \nuniform sampler2D in_noiseSampler;\
145  \n#ifndef GL_ES\
146  \nuniform sampler2D in_depthSampler;\
147  \n#endif\
148  \n\
149  \n// Camera position\
150  \nuniform vec3 in_cameraPos;\
151  \n\
152  \n// view and model matrices\
153  \nuniform mat4 in_volumeMatrix;\
154  \nuniform mat4 in_inverseVolumeMatrix;\
155  \nuniform mat4 in_projectionMatrix;\
156  \nuniform mat4 in_inverseProjectionMatrix;\
157  \nuniform mat4 in_modelViewMatrix;\
158  \nuniform mat4 in_inverseModelViewMatrix;\
159  \nuniform mat4 in_textureDatasetMatrix;\
160  \nuniform mat4 in_inverseTextureDatasetMatrix;\
161  \nvarying mat4 ip_inverseTextureDataAdjusted;\
162  \nuniform vec3 in_texMin;\
163  \nuniform vec3 in_texMax;\
164  \nuniform mat4 in_textureToEye;\
165  \n\
166  \n// Ray step size\
167  \nuniform vec3 in_cellStep;\
168  \nuniform vec2 in_scalarsRange[4];\
169  \nuniform vec3 in_cellSpacing;\
170  \n\
171  \n// Sample distance\
172  \nuniform float in_sampleDistance;\
173  \n\
174  \n// Scales\
175  \nuniform vec3 in_cellScale;\
176  \nuniform vec2 in_windowLowerLeftCorner;\
177  \nuniform vec2 in_inverseOriginalWindowSize;\
178  \nuniform vec2 in_inverseWindowSize;\
179  \nuniform vec3 in_textureExtentsMax;\
180  \nuniform vec3 in_textureExtentsMin;\
181  \n\
182  \n// Material and lighting\
183  \nuniform vec3 in_diffuse[4];\
184  \nuniform vec3 in_ambient[4];\
185  \nuniform vec3 in_specular[4];\
186  \nuniform float in_shininess[4];\
187  \n\
188  \n// Others\
189  \nuniform bool in_cellFlag;\
190  \nuniform bool in_useJittering;\
191  \nvec3 g_rayJitter = vec3(0.0);\
192  \nuniform bool in_clampDepthToBackface;\
193  \n\
194  \nuniform vec2 in_averageIPRange;"
195  );
196 
197  if (lightingComplexity > 0 || hasGradientOpacity)
198  {
199  shaderStr += std::string("\
200  \nuniform bool in_twoSidedLighting;\
201  \nvec3 g_xvec;\
202  \nvec3 g_yvec;\
203  \nvec3 g_zvec;");
204  }
205 
206  if (hasGradientOpacity)
207  {
208  shaderStr += std::string("\
209  \nvec3 g_aspect;\
210  \nvec3 g_cellSpacing;\
211  \nfloat g_avgSpacing;");
212  }
213 
214  if (lightingComplexity == 3)
215  {
216  shaderStr += std::string("\
217  \nvec4 g_fragWorldPos;\
218  \nuniform int in_numberOfLights;\
219  \nuniform vec3 in_lightAmbientColor[6];\
220  \nuniform vec3 in_lightDiffuseColor[6];\
221  \nuniform vec3 in_lightSpecularColor[6];\
222  \nuniform vec3 in_lightDirection[6];\
223  \nuniform vec3 in_lightPosition[6];\
224  \nuniform vec3 in_lightAttenuation[6];\
225  \nuniform float in_lightConeAngle[6];\
226  \nuniform float in_lightExponent[6];\
227  \nuniform int in_lightPositional[6];\
228  ");
229  }
230  else if (lightingComplexity == 2)
231  {
232  shaderStr += std::string("\
233  \nvec4 g_fragWorldPos;\
234  \nuniform int in_numberOfLights;\
235  \nuniform vec3 in_lightAmbientColor[6];\
236  \nuniform vec3 in_lightDiffuseColor[6];\
237  \nuniform vec3 in_lightSpecularColor[6];\
238  \nuniform vec3 in_lightDirection[6];\
239  ");
240  }
241  else
242  {
243  shaderStr += std::string("\
244  \nuniform vec3 in_lightAmbientColor[1];\
245  \nuniform vec3 in_lightDiffuseColor[1];\
246  \nuniform vec3 in_lightSpecularColor[1];\
247  \nvec4 g_lightPosObj;\
248  \nvec3 g_ldir;\
249  \nvec3 g_vdir;\
250  \nvec3 g_h;");
251  }
252 
253  if (noOfComponents > 1 && independentComponents)
254  {
255  shaderStr += std::string("\
256  \nuniform vec4 in_componentWeight;");
257  }
258 
262  glMapper->GetUseDepthPass())
263  {
264  shaderStr += std::string("\
265  \nuniform sampler2D in_depthPassSampler;");
266  }
267 
268  return shaderStr;
269  }
270 
271  //--------------------------------------------------------------------------
272  std::string BaseInit(vtkRenderer* vtkNotUsed(ren),
273  vtkVolumeMapper* mapper,
274  vtkVolume* vol,
275  int lightingComplexity)
276  {
279 
280  std::string shaderStr = std::string("\
281  \n bool l_adjustTextureExtents = !in_cellFlag;"
282  );
283 
285  glMapper->GetUseDepthPass() && glMapper->GetBlendMode() ==
287  {
288  shaderStr += std::string("\
289  \n //\
290  \n vec2 fragTexCoord2 = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
291  \n in_inverseWindowSize;\
292  \n vec4 depthValue = texture2D(in_depthPassSampler, fragTexCoord2);\
293  \n vec4 dataPos = WindowToNDC(gl_FragCoord.x, gl_FragCoord.y, depthValue.x);\
294  \n\
295  \n // From normalized device coordinates to eye coordinates.\
296  \n // in_projectionMatrix is inversed because of way VT\
297  \n // From eye coordinates to texture coordinates\
298  \n dataPos = in_inverseTextureDatasetMatrix *\
299  \n in_inverseVolumeMatrix *\
300  \n in_inverseModelViewMatrix *\
301  \n in_inverseProjectionMatrix *\
302  \n dataPos;\
303  \n dataPos /= dataPos.w;\
304  \n g_dataPos = dataPos.xyz;\
305  \n l_adjustTextureExtents = true;"
306  );
307  }
308  else
309  {
310  shaderStr += std::string("\
311  \n // Get the 3D texture coordinates for lookup into the in_volume dataset\
312  \n g_dataPos = ip_textureCoords.xyz;"
313  );
314  }
315 
316  shaderStr += std::string("\
317  \n\
318  \n // Eye position in dataset space\
319  \n g_eyePosObj = (in_inverseVolumeMatrix * vec4(in_cameraPos, 1.0));\
320  \n if (g_eyePosObj.w != 0.0)\
321  \n {\
322  \n g_eyePosObj.x /= g_eyePosObj.w;\
323  \n g_eyePosObj.y /= g_eyePosObj.w;\
324  \n g_eyePosObj.z /= g_eyePosObj.w;\
325  \n g_eyePosObj.w = 1.0;\
326  \n }\
327  \n\
328  \n // Getting the ray marching direction (in dataset space);\
329  \n vec3 rayDir = computeRayDirection();\
330  \n\
331  \n // Multiply the raymarching direction with the step size to get the\
332  \n // sub-step size we need to take at each raymarching step\
333  \n g_dirStep = (ip_inverseTextureDataAdjusted *\
334  \n vec4(rayDir, 0.0)).xyz * in_sampleDistance;\
335  \n\
336  \n // 2D Texture fragment coordinates [0,1] from fragment coordinates.\
337  \n // The frame buffer texture has the size of the plain buffer but \
338  \n // we use a fraction of it. The texture coordinate is less than 1 if\
339  \n // the reduction factor is less than 1.\
340  \n // Device coordinates are between -1 and 1. We need texture\
341  \n // coordinates between 0 and 1. The in_noiseSampler and in_depthSampler\
342  \n // buffers have the original size buffer.\
343  \n vec2 fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
344  \n in_inverseWindowSize;\
345  \n\
346  \n if (in_useJittering)\
347  \n {\
348  \n float jitterValue = texture2D(in_noiseSampler, fragTexCoord).x;\
349  \n g_rayJitter = g_dirStep * jitterValue;\
350  \n g_dataPos += g_rayJitter;\
351  \n }\
352  \n else\
353  \n {\
354  \n g_dataPos += g_dirStep;\
355  \n }\
356  \n\
357  \n // Flag to deternmine if voxel should be considered for the rendering\
358  \n g_skip = false;");
359 
360  if (vol->GetProperty()->GetShade() && lightingComplexity == 1)
361  {
362  shaderStr += std::string("\
363  \n // Light position in dataset space\
364  \n g_lightPosObj = (in_inverseVolumeMatrix *\
365  \n vec4(in_cameraPos, 1.0));\
366  \n if (g_lightPosObj.w != 0.0)\
367  \n {\
368  \n g_lightPosObj.x /= g_lightPosObj.w;\
369  \n g_lightPosObj.y /= g_lightPosObj.w;\
370  \n g_lightPosObj.z /= g_lightPosObj.w;\
371  \n g_lightPosObj.w = 1.0;\
372  \n }\
373  \n g_ldir = normalize(g_lightPosObj.xyz - ip_vertexPos);\
374  \n g_vdir = normalize(g_eyePosObj.xyz - ip_vertexPos);\
375  \n g_h = normalize(g_ldir + g_vdir);"
376  );
377  }
378  if ( (vol->GetProperty()->GetShade() ||
379  vol->GetProperty()->HasGradientOpacity()) &&
381  {
382  shaderStr += std::string("\
383  \n g_xvec = vec3(in_cellStep[0], 0.0, 0.0);\
384  \n g_yvec = vec3(0.0, in_cellStep[1], 0.0);\
385  \n g_zvec = vec3(0.0, 0.0, in_cellStep[2]);"
386  );
387  }
388 
389  if (vol->GetProperty()->HasGradientOpacity())
390  {
391  shaderStr += std::string("\
392  \n g_cellSpacing = vec3(in_cellSpacing[0],\
393  \n in_cellSpacing[1],\
394  \n in_cellSpacing[2]);\
395  \n g_avgSpacing = (g_cellSpacing[0] +\
396  \n g_cellSpacing[1] +\
397  \n g_cellSpacing[2])/3.0;\
398  \n // Adjust the aspect\
399  \n g_aspect.x = g_cellSpacing[0] * 2.0 / g_avgSpacing;\
400  \n g_aspect.y = g_cellSpacing[1] * 2.0 / g_avgSpacing;\
401  \n g_aspect.z = g_cellSpacing[2] * 2.0 / g_avgSpacing;"
402  );
403  }
404 
405  return shaderStr;
406  }
407 
408  //--------------------------------------------------------------------------
410  vtkVolumeMapper* vtkNotUsed(mapper),
411  vtkVolume* vtkNotUsed(vol))
412  {
413  return std::string("\
414  \n g_skip = false;"
415  );
416  }
417 
418  //--------------------------------------------------------------------------
419  std::string BaseExit(vtkRenderer* vtkNotUsed(ren),
420  vtkVolumeMapper* vtkNotUsed(mapper),
421  vtkVolume* vtkNotUsed(vol))
422  {
423  return std::string();
424  }
425 
426  //--------------------------------------------------------------------------
428  vtkVolumeMapper* vtkNotUsed(mapper),
429  vtkVolume* vol,
430  int noOfComponents,
431  int independentComponents,
432  std::map<int, std::string>
433  gradientTableMap)
434  {
435  std::string shaderStr;
436  if (vol->GetProperty()->HasGradientOpacity() &&
437  (noOfComponents == 1 || !independentComponents))
438  {
439  shaderStr += std::string("\
440  \nuniform sampler2D in_gradientTransferFunc;\
441  \nfloat computeGradientOpacity(vec4 grad)\
442  \n {\
443  \n return texture2D("+gradientTableMap[0]+", vec2(grad.w, 0.0)).r;\
444  \n }"
445  );
446  }
447  else if (noOfComponents > 1 && independentComponents &&
449  {
450  std::ostringstream toString;
451  for (int i = 0; i < noOfComponents; ++i)
452  {
453  shaderStr += std::string("\n uniform sampler2D ") +
454  gradientTableMap[i] + std::string(";");
455  }
456 
457  shaderStr += std::string("\
458  \nfloat computeGradientOpacity(vec4 grad, int component)\
459  \n {");
460 
461  for (int i = 0; i < noOfComponents; ++i)
462  {
463  toString << i;
464  shaderStr += std::string("\
465  \n if (component == " + toString.str() + ")");
466 
467  shaderStr += std::string("\
468  \n {\
469  \n return texture2D("+ gradientTableMap[i] + ", vec2(grad.w, 0.0)).r;\
470  \n }"
471  );
472 
473  // Reset
474  toString.str("");
475  toString.clear();
476  }
477 
478  shaderStr += std::string("\
479  \n }");
480  }
481 
482  if (vol->GetProperty()->GetShade() &&
483  !vol->GetProperty()->HasGradientOpacity())
484  {
485  shaderStr += std::string("\
486  \n// c is short for component\
487  \nvec4 computeGradient(int c)\
488  \n {\
489  \n // Approximate Nabla(F) derivatives with central differences.\
490  \n vec3 g1; // F_front\
491  \n vec3 g2; // F_back\
492  \n g1.x = texture3D(in_volume, vec3(g_dataPos + g_xvec))[c];\
493  \n g1.y = texture3D(in_volume, vec3(g_dataPos + g_yvec))[c];\
494  \n g1.z = texture3D(in_volume, vec3(g_dataPos + g_zvec))[c];\
495  \n g2.x = texture3D(in_volume, vec3(g_dataPos - g_xvec))[c];\
496  \n g2.y = texture3D(in_volume, vec3(g_dataPos - g_yvec))[c];\
497  \n g2.z = texture3D(in_volume, vec3(g_dataPos - g_zvec))[c];\
498  \n\
499  \n // Apply scale and bias to the fetched values.\
500  \n g1 = g1 * in_volume_scale[c] + in_volume_bias[c];\
501  \n g2 = g2 * in_volume_scale[c] + in_volume_bias[c];\
502  \n\
503  \n // Central differences: (F_front - F_back) / 2h\
504  \n // This version of computeGradient() is only used for lighting\
505  \n // calculations (only direction matters), hence the difference is\
506  \n // not scaled by 2h and a dummy gradient mag is returned (-1.).\
507  \n return vec4((g1 - g2), -1.0);\
508  \n }"
509  );
510  }
511  else if (vol->GetProperty()->HasGradientOpacity())
512  {
513  shaderStr += std::string("\
514  \n// c is short for component\
515  \nvec4 computeGradient(int c)\
516  \n {\
517  \n // Approximate Nabla(F) derivatives with central differences.\
518  \n vec3 g1; // F_front\
519  \n vec3 g2; // F_back\
520  \n g1.x = texture3D(in_volume, vec3(g_dataPos + g_xvec))[c];\
521  \n g1.y = texture3D(in_volume, vec3(g_dataPos + g_yvec))[c];\
522  \n g1.z = texture3D(in_volume, vec3(g_dataPos + g_zvec))[c];\
523  \n g2.x = texture3D(in_volume, vec3(g_dataPos - g_xvec))[c];\
524  \n g2.y = texture3D(in_volume, vec3(g_dataPos - g_yvec))[c];\
525  \n g2.z = texture3D(in_volume, vec3(g_dataPos - g_zvec))[c];\
526  \n\
527  \n // Apply scale and bias to the fetched values.\
528  \n g1 = g1 * in_volume_scale[c] + in_volume_bias[c];\
529  \n g2 = g2 * in_volume_scale[c] + in_volume_bias[c];\
530  \n\
531  \n // Scale values the actual scalar range.\
532  \n float range = in_scalarsRange[c][1] - in_scalarsRange[c][0];\
533  \n g1 = in_scalarsRange[c][0] + range * g1;\
534  \n g2 = in_scalarsRange[c][0] + range * g2;\
535  \n\
536  \n // Central differences: (F_front - F_back) / 2h\
537  \n g2 = g1 - g2;\
538  \n g2 /= g_aspect;\
539  \n float grad_mag = length(g2);\
540  \n\
541  \n // Handle normalizing with grad_mag == 0.0\
542  \n g2 = grad_mag > 0.0 ? normalize(g2) : vec3(0.0);\
543  \n\
544  \n // Since the actual range of the gradient magnitude is unknown,\
545  \n // assume it is in the range [0, 0.25 * dataRange].\
546  \n range = range != 0 ? range : 1.0;\
547  \n grad_mag = grad_mag / (0.25 * range);\
548  \n grad_mag = clamp(grad_mag, 0.0, 1.0);\
549  \n\
550  \n return vec4(g2.xyz, grad_mag);\
551  \n }");
552  }
553  else
554  {
555  shaderStr += std::string("\
556  \nvec4 computeGradient(int component)\
557  \n {\
558  \n return vec4(0.0);\
559  \n }");
560  }
561 
562  return shaderStr;
563  }
564 
565  //--------------------------------------------------------------------------
567  vtkVolumeMapper* mapper,
568  vtkVolume* vol,
569  int noOfComponents,
570  int independentComponents,
571  int vtkNotUsed(numberOfLights),
572  int lightingComplexity)
573  {
574  vtkVolumeProperty* volProperty = vol->GetProperty();
575  std::string shaderStr = std::string("\
576  \nvec4 computeLighting(vec4 color, int component)\
577  \n {\
578  \n vec4 finalColor = vec4(0.0);"
579  );
580 
581  // Shading for composite blending only
582  int shadeReqd = volProperty->GetShade() &&
583  (mapper->GetBlendMode() ==
585 
586  if (shadeReqd || volProperty->HasGradientOpacity())
587  {
588  shaderStr += std::string("\
589  \n // Compute gradient function only once\
590  \n vec4 gradient = computeGradient(component);"
591  );
592  }
593 
594  if (shadeReqd)
595  {
596  if (lightingComplexity == 1)
597  {
598  shaderStr += std::string("\
599  \n vec3 diffuse = vec3(0.0);\
600  \n vec3 specular = vec3(0.0);\
601  \n vec3 normal = gradient.xyz / in_cellSpacing;\
602  \n float normalLength = length(normal);\
603  \n if (normalLength > 0.0)\
604  \n {\
605  \n normal = normalize(normal);\
606  \n }\
607  \n else\
608  \n {\
609  \n normal = vec3(0.0, 0.0, 0.0);\
610  \n }\
611  \n float nDotL = dot(normal, g_ldir);\
612  \n float nDotH = dot(normal, g_h);\
613  \n if (nDotL < 0.0 && in_twoSidedLighting)\
614  \n {\
615  \n nDotL = -nDotL;\
616  \n }\
617  \n if (nDotH < 0.0 && in_twoSidedLighting)\
618  \n {\
619  \n nDotH = -nDotH;\
620  \n }\
621  \n if (nDotL > 0.0)\
622  \n {\
623  \n diffuse = nDotL * in_diffuse[component] *\
624  \n in_lightDiffuseColor[0] * color.rgb;\
625  \n }\
626  \n specular = pow(nDotH, in_shininess[component]) *\
627  \n in_specular[component] *\
628  \n in_lightSpecularColor[0];\
629  \n // For the headlight, ignore the light's ambient color\
630  \n // for now as it is causing the old mapper tests to fail\
631  \n finalColor.xyz = in_ambient[component] * color.rgb +\
632  \n diffuse + specular;"
633  );
634  }
635  else if (lightingComplexity == 2)
636  {
637  shaderStr += std::string("\
638  \n g_fragWorldPos = in_modelViewMatrix * in_volumeMatrix *\
639  \n in_textureDatasetMatrix * vec4(-g_dataPos, 1.0);\
640  \n if (g_fragWorldPos.w != 0.0)\
641  \n {\
642  \n g_fragWorldPos /= g_fragWorldPos.w;\
643  \n }\
644  \n vec3 vdir = normalize(g_fragWorldPos.xyz);\
645  \n vec3 normal = gradient.xyz;\
646  \n vec3 ambient = vec3(0.0);\
647  \n vec3 diffuse = vec3(0.0);\
648  \n vec3 specular = vec3(0.0);\
649  \n float normalLength = length(normal);\
650  \n if (normalLength > 0.0)\
651  \n {\
652  \n normal = normalize((in_textureToEye * vec4(normal, 0.0)).xyz);\
653  \n }\
654  \n else\
655  \n {\
656  \n normal = vec3(0.0, 0.0, 0.0);\
657  \n }\
658  \n for (int lightNum = 0; lightNum < in_numberOfLights; lightNum++)\
659  \n {\
660  \n vec3 ldir = in_lightDirection[lightNum].xyz;\
661  \n vec3 h = normalize(ldir + vdir);\
662  \n float nDotH = dot(normal, h);\
663  \n if (nDotH < 0.0 && in_twoSidedLighting)\
664  \n {\
665  \n nDotH = -nDotH;\
666  \n }\
667  \n float nDotL = dot(normal, ldir);\
668  \n if (nDotL < 0.0 && in_twoSidedLighting)\
669  \n {\
670  \n nDotL = -nDotL;\
671  \n }\
672  \n if (nDotL > 0.0)\
673  \n {\
674  \n diffuse += in_lightDiffuseColor[lightNum] * nDotL;\
675  \n }\
676  \n if (nDotH > 0.0)\
677  \n {\
678  \n specular = in_lightSpecularColor[lightNum] *\
679  \n pow(nDotH, in_shininess[component]);\
680  \n }\
681  \n ambient += in_lightAmbientColor[lightNum];\
682  \n }\
683  \n finalColor.xyz = in_ambient[component] * ambient +\
684  \n in_diffuse[component] * diffuse * color.rgb +\
685  \n in_specular[component] * specular;"
686  );
687  }
688  else if (lightingComplexity == 3)
689  {
690  shaderStr += std::string("\
691  \n g_fragWorldPos = in_modelViewMatrix * in_volumeMatrix *\
692  \n in_textureDatasetMatrix * vec4(g_dataPos, 1.0);\
693  \n if (g_fragWorldPos.w != 0.0)\
694  \n {\
695  \n g_fragWorldPos /= g_fragWorldPos.w;\
696  \n }\
697  \n vec3 viewDirection = normalize(-g_fragWorldPos.xyz);\
698  \n vec3 ambient = vec3(0,0,0);\
699  \n vec3 diffuse = vec3(0,0,0);\
700  \n vec3 specular = vec3(0,0,0);\
701  \n vec3 vertLightDirection;\
702  \n vec3 normal = normalize((in_textureToEye * vec4(gradient.xyz, 0.0)).xyz);\
703  \n vec3 lightDir;\
704  \n for (int lightNum = 0; lightNum < in_numberOfLights; lightNum++)\
705  \n {\
706  \n float attenuation = 1.0;\
707  \n // directional\
708  \n lightDir = in_lightDirection[lightNum];\
709  \n if (in_lightPositional[lightNum] == 0)\
710  \n {\
711  \n vertLightDirection = lightDir;\
712  \n }\
713  \n else\
714  \n {\
715  \n vertLightDirection = (g_fragWorldPos.xyz - in_lightPosition[lightNum]);\
716  \n float distance = length(vertLightDirection);\
717  \n vertLightDirection = normalize(vertLightDirection);\
718  \n attenuation = 1.0 /\
719  \n (in_lightAttenuation[lightNum].x\
720  \n + in_lightAttenuation[lightNum].y * distance\
721  \n + in_lightAttenuation[lightNum].z * distance * distance);\
722  \n // per OpenGL standard cone angle is 90 or less for a spot light\
723  \n if (in_lightConeAngle[lightNum] <= 90.0)\
724  \n {\
725  \n float coneDot = dot(vertLightDirection, lightDir);\
726  \n // if inside the cone\
727  \n if (coneDot >= cos(radians(in_lightConeAngle[lightNum])))\
728  \n {\
729  \n attenuation = attenuation * pow(coneDot, in_lightExponent[lightNum]);\
730  \n }\
731  \n else\
732  \n {\
733  \n attenuation = 0.0;\
734  \n }\
735  \n }\
736  \n }\
737  \n // diffuse and specular lighting\
738  \n float nDotL = dot(normal, vertLightDirection);\
739  \n if (nDotL < 0.0 && in_twoSidedLighting)\
740  \n {\
741  \n nDotL = -nDotL;\
742  \n }\
743  \n if (nDotL > 0.0)\
744  \n {\
745  \n float df = max(0.0, attenuation * nDotL);\
746  \n diffuse += (df * in_lightDiffuseColor[lightNum]);\
747  \n }\
748  \n vec3 h = normalize(vertLightDirection + viewDirection);\
749  \n float nDotH = dot(normal, h);\
750  \n if (nDotH < 0.0 && in_twoSidedLighting)\
751  \n {\
752  \n nDotH = -nDotH;\
753  \n }\
754  \n if (nDotH > 0.0)\
755  \n {\
756  \n float sf = attenuation * pow(nDotH, in_shininess[component]);\
757  \n specular += (sf * in_lightSpecularColor[lightNum]);\
758  \n }\
759  \n ambient += in_lightAmbientColor[lightNum];\
760  \n }\
761  \n finalColor.xyz = in_ambient[component] * ambient +\
762  \n in_diffuse[component] * diffuse * color.rgb +\
763  \n in_specular[component] * specular;\
764  ");
765  }
766  }
767  else
768  {
769  shaderStr += std::string(
770  "\n finalColor = vec4(color.rgb, 0.0);"
771  );
772  }
773 
774  if (volProperty->HasGradientOpacity() &&
775  (noOfComponents == 1 || !independentComponents))
776  {
777  shaderStr += std::string("\
778  \n if (gradient.w >= 0.0)\
779  \n {\
780  \n color.a = color.a *\
781  \n computeGradientOpacity(gradient);\
782  \n }"
783  );
784  }
785  else if (noOfComponents > 1 && independentComponents &&
786  volProperty->HasGradientOpacity())
787  {
788  shaderStr += std::string("\
789  \n if (gradient.w >= 0.0)\
790  \n {\
791  \n for (int i = 0; i < in_noOfComponents; ++i)\
792  \n {\
793  \n color.a = color.a *\
794  \n computeGradientOpacity(gradient, i) * in_componentWeight[i];\
795  \n }\
796  \n }"
797  );
798  }
799 
800  shaderStr += std::string("\
801  \n finalColor.a = color.a;\
802  \n return finalColor;\
803  \n }"
804  );
805 
806  return shaderStr;
807  }
808 
809  //--------------------------------------------------------------------------
811  vtkVolumeMapper* vtkNotUsed(mapper),
812  vtkVolume* vtkNotUsed(vol),
813  int vtkNotUsed(noOfComponents))
814  {
815  if (!ren->GetActiveCamera()->GetParallelProjection())
816  {
817  return std::string("\
818  \nvec3 computeRayDirection()\
819  \n {\
820  \n return normalize(ip_vertexPos.xyz - g_eyePosObj.xyz);\
821  \n }");
822  }
823  else
824  {
825  return std::string("\
826  \nuniform vec3 in_projectionDirection;\
827  \nvec3 computeRayDirection()\
828  \n {\
829  \n return normalize((in_inverseVolumeMatrix *\
830  \n vec4(in_projectionDirection, 0.0)).xyz);\
831  \n }");
832  }
833  }
834 
835  //--------------------------------------------------------------------------
837  vtkVolumeMapper* vtkNotUsed(mapper),
838  vtkVolume* vtkNotUsed(vol),
839  int noOfComponents,
840  int independentComponents,
841  std::map<int, std::string> colorTableMap)
842  {
843  if (noOfComponents == 1)
844  {
845  return std::string("\
846  \nuniform sampler2D in_colorTransferFunc;\
847  \nvec4 computeColor(vec4 scalar, float opacity)\
848  \n {\
849  \n return computeLighting(vec4(texture2D(in_colorTransferFunc,\
850  \n vec2(scalar.w, 0.0)).xyz, opacity), 0);\
851  \n }");
852  }
853  else if (noOfComponents > 1 && independentComponents)
854  {
855  std::string shaderStr;
856  std::ostringstream toString;
857  for (int i = 0; i < noOfComponents; ++i)
858  {
859  shaderStr += std::string("\n uniform sampler2D ") +
860  colorTableMap[i] + std::string(";");
861  }
862 
863  shaderStr += std::string("\
864  \nvec4 computeColor(vec4 scalar, float opacity, int component)\
865  \n {");
866 
867  for (int i = 0; i < noOfComponents; ++i)
868  {
869  toString << i;
870  shaderStr += std::string("\
871  \n if (component == " + toString.str() + ")");
872 
873  shaderStr += std::string("\
874  \n {\
875  \n return computeLighting(vec4(texture2D(\
876  \n "+colorTableMap[i]);
877  shaderStr += std::string(", vec2(\
878  \n scalar[" + toString.str() + "],0.0)).xyz,\
879  \n opacity),"+toString.str()+");\
880  \n }");
881 
882  // Reset
883  toString.str("");
884  toString.clear();
885  }
886 
887  shaderStr += std::string("\n }");
888  return shaderStr;
889  }
890  else if (noOfComponents == 2 && !independentComponents)
891  {
892  return std::string("\
893  \nuniform sampler2D in_colorTransferFunc;\
894  \nvec4 computeColor(vec4 scalar, float opacity)\
895  \n {\
896  \n return computeLighting(vec4(texture2D(in_colorTransferFunc,\
897  \n vec2(scalar.x, 0.0)).xyz,\
898  \n opacity), 0);\
899  \n }");
900  }
901  else
902  {
903  return std::string("\
904  \nvec4 computeColor(vec4 scalar, float opacity)\
905  \n {\
906  \n return computeLighting(vec4(scalar.xyz, opacity), 0);\
907  \n }");
908  }
909  }
910 
911  //--------------------------------------------------------------------------
913  vtkVolumeMapper* vtkNotUsed(mapper),
914  vtkVolume* vtkNotUsed(vol),
915  int noOfComponents,
916  int independentComponents,
917  std::map<int, std::string> opacityTableMap)
918  {
919  if (noOfComponents > 1 && independentComponents)
920  {
921  std::string shaderStr;
922  std::ostringstream toString;
923 
924  for (int i = 0; i < noOfComponents; ++i)
925  {
926  shaderStr += std::string("\n uniform sampler2D ") +
927  opacityTableMap[i] + std::string(";");
928 
929  }
930 
931  shaderStr += std::string("\
932  \nfloat computeOpacity(vec4 scalar, int component)\
933  \n {");
934 
935  for (int i = 0; i < noOfComponents; ++i)
936  {
937  toString << i;
938  shaderStr += std::string("\
939  \n if (component == " + toString.str() + ")");
940 
941  shaderStr += std::string("\
942  \n {\
943  \n return texture2D(in_opacityTransferFunc");
944  shaderStr += (i == 0 ? "" : toString.str());
945  shaderStr += std::string(",vec2(scalar[" + toString.str() + "],0)).r;\
946  \n }");
947 
948  // Reset
949  toString.str("");
950  toString.clear();
951  }
952 
953  shaderStr += std::string("\n }");
954  return shaderStr;
955  }
956  else if (noOfComponents == 2 && !independentComponents)
957  {
958  return std::string("\
959  \nuniform sampler2D in_opacityTransferFunc;\
960  \nfloat computeOpacity(vec4 scalar)\
961  \n {\
962  \n return texture2D(in_opacityTransferFunc, vec2(scalar.y, 0)).r;\
963  \n }");
964  }
965  else
966  {
967  return std::string("\
968  \nuniform sampler2D in_opacityTransferFunc;\
969  \nfloat computeOpacity(vec4 scalar)\
970  \n {\
971  \n return texture2D(in_opacityTransferFunc, vec2(scalar.w, 0)).r;\
972  \n }");
973  }
974  }
975 
976  //--------------------------------------------------------------------------
978  vtkVolumeMapper* vtkNotUsed(mapper),
979  vtkVolume* vtkNotUsed(vol))
980  {
981  return std::string();
982  }
983 
984  //--------------------------------------------------------------------------
986  vtkVolumeMapper* mapper,
987  vtkVolume* vtkNotUsed(vol))
988  {
990  {
991  return std::string("\
992  \n bool l_firstValue;\
993  \n vec4 l_maxValue;");
994  }
995  else if (mapper->GetBlendMode() ==
997  {
998  return std::string("\
999  \n bool l_firstValue;\
1000  \n vec4 l_minValue;");
1001  }
1003  {
1004  return std::string("\
1005  \n uvec4 l_numSamples;\
1006  \n vec4 l_avgValue;");
1007  }
1008  else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
1009  {
1010  return std::string("\
1011  \n vec4 l_sumValue;");
1012  }
1013  else
1014  {
1015  return std::string();
1016  }
1017  }
1018 
1019  //--------------------------------------------------------------------------
1021  vtkVolumeMapper* mapper,
1022  vtkVolume* vtkNotUsed(vol))
1023  {
1025  {
1026  return std::string("\
1027  \n // We get data between 0.0 - 1.0 range\
1028  \n l_firstValue = true;\
1029  \n l_maxValue = vec4(0.0);"
1030  );
1031  }
1032  else if (mapper->GetBlendMode() ==
1034  {
1035  return std::string("\
1036  \n //We get data between 0.0 - 1.0 range\
1037  \n l_firstValue = true;\
1038  \n l_minValue = vec4(1.0);"
1039  );
1040  }
1042  {
1043  return std::string("\
1044  \n //We get data between 0.0 - 1.0 range\
1045  \n l_avgValue = vec4(0.0);\
1046  \n // Keep track of number of samples\
1047  \n l_numSamples = uvec4(0);"
1048  );
1049  }
1050  else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
1051  {
1052  return std::string("\
1053  \n //We get data between 0.0 - 1.0 range\
1054  \n l_sumValue = vec4(0.0);"
1055  );
1056  }
1057  else
1058  {
1059  return std::string();
1060  }
1061  }
1062 
1063  //--------------------------------------------------------------------------
1065  vtkVolumeMapper* mapper,
1066  vtkVolume* vtkNotUsed(vol),
1067  vtkImageData* maskInput,
1068  vtkVolumeMask* mask, int maskType,
1069  int noOfComponents,
1070  int independentComponents = 0)
1071  {
1074  std::string shaderStr = std::string("\
1075  \n if (!g_skip)\
1076  \n {\
1077  \n vec4 scalar = texture3D(in_volume, g_dataPos);"
1078  );
1079 
1080  // simulate old intensity textures
1081  if (noOfComponents == 1)
1082  {
1083  shaderStr += std::string("\
1084  \n scalar.r = scalar.r*in_volume_scale.r + in_volume_bias.r;\
1085  \n scalar = vec4(scalar.r,scalar.r,scalar.r,scalar.r);"
1086  );
1087  }
1088  else
1089  {
1090  // handle bias and scale
1091  shaderStr += std::string("\
1092  \n scalar = scalar*in_volume_scale + in_volume_bias;"
1093  );
1094  }
1095 
1097  {
1098  if (noOfComponents > 1)
1099  {
1100  if (!independentComponents)
1101  {
1102  shaderStr += std::string("\
1103  \n if (l_maxValue.w < scalar.w || l_firstValue)\
1104  \n {\
1105  \n l_maxValue = scalar;\
1106  \n }\
1107  \n\
1108  \n if (l_firstValue)\
1109  \n {\
1110  \n l_firstValue = false;\
1111  \n }"
1112  );
1113  }
1114  else
1115  {
1116  shaderStr += std::string("\
1117  \n for (int i = 0; i < in_noOfComponents; ++i)\
1118  \n {\
1119  \n if (l_maxValue[i] < scalar[i] || l_firstValue)\
1120  \n {\
1121  \n l_maxValue[i] = scalar[i];\
1122  \n }\
1123  \n }\
1124  \n if (l_firstValue)\
1125  \n {\
1126  \n l_firstValue = false;\
1127  \n }"
1128  );
1129  }
1130  }
1131  else
1132  {
1133  shaderStr += std::string("\
1134  \n if (l_maxValue.w < scalar.x || l_firstValue)\
1135  \n {\
1136  \n l_maxValue.w = scalar.x;\
1137  \n }\
1138  \n\
1139  \n if (l_firstValue)\
1140  \n {\
1141  \n l_firstValue = false;\
1142  \n }"
1143  );
1144  }
1145  }
1147  {
1148  if (noOfComponents > 1)
1149  {
1150  if (!independentComponents)
1151  {
1152  shaderStr += std::string("\
1153  \n if (l_minValue.w > scalar.w || l_firstValue)\
1154  \n {\
1155  \n l_minValue = scalar;\
1156  \n }\
1157  \n\
1158  \n if (l_firstValue)\
1159  \n {\
1160  \n l_firstValue = false;\
1161  \n }"
1162  );
1163  }
1164  else
1165  {
1166  shaderStr += std::string("\
1167  \n for (int i = 0; i < in_noOfComponents; ++i)\
1168  \n {\
1169  \n if (l_minValue[i] < scalar[i] || l_firstValue)\
1170  \n {\
1171  \n l_minValue[i] = scalar[i];\
1172  \n }\
1173  \n }\
1174  \n if (l_firstValue)\
1175  \n {\
1176  \n l_firstValue = false;\
1177  \n }"
1178  );
1179  }
1180  }
1181  else
1182  {
1183  shaderStr += std::string("\
1184  \n if (l_minValue.w > scalar.x || l_firstValue)\
1185  \n {\
1186  \n l_minValue.w = scalar.x;\
1187  \n }\
1188  \n\
1189  \n if (l_firstValue)\
1190  \n {\
1191  \n l_firstValue = false;\
1192  \n }"
1193  );
1194  }
1195  }
1197  {
1198  if (noOfComponents > 1 && independentComponents)
1199  {
1200  shaderStr += std::string("\
1201  \n for (int i = 0; i < in_noOfComponents; ++i)\
1202  \n {\
1203  \n // Get the intensity in volume scalar range\
1204  \n float intensity = in_scalarsRange[i][0] +\
1205  \n (in_scalarsRange[i][1] -\
1206  \n in_scalarsRange[i][0]) * scalar[i];\
1207  \n if (in_averageIPRange.x <= intensity &&\
1208  \n intensity <= in_averageIPRange.y)\
1209  \n {\
1210  \n l_avgValue[i] += computeOpacity(scalar, i) * scalar[i];\
1211  \n ++l_numSamples[i];\
1212  \n }\
1213  \n }"
1214  );
1215  }
1216  else
1217  {
1218  shaderStr += std::string("\
1219  \n // Get the intensity in volume scalar range\
1220  \n float intensity = in_scalarsRange[0][0] +\
1221  \n (in_scalarsRange[0][1] -\
1222  \n in_scalarsRange[0][0]) * scalar.x;\
1223  \n if (in_averageIPRange.x <= intensity &&\
1224  \n intensity <= in_averageIPRange.y)\
1225  \n {\
1226  \n l_avgValue.x += computeOpacity(scalar) * scalar.x;\
1227  \n ++l_numSamples.x;\
1228  \n }"
1229  );
1230  }
1231  }
1232  else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
1233  {
1234  if (noOfComponents > 1 && independentComponents)
1235  {
1236  shaderStr += std::string("\
1237  \n for (int i = 0; i < in_noOfComponents; ++i)\
1238  \n {\
1239  \n float opacity = computeOpacity(scalar, i);\
1240  \n l_sumValue[i] = l_sumValue[i] + opacity * scalar[i];\
1241  \n }"
1242  );
1243  }
1244  else
1245  {
1246  shaderStr += std::string("\
1247  \n float opacity = computeOpacity(scalar);\
1248  \n l_sumValue.x = l_sumValue.x + opacity * scalar.x;"
1249  );
1250  }
1251  }
1252  else if (mapper->GetBlendMode() == vtkVolumeMapper::COMPOSITE_BLEND)
1253  {
1254  if (noOfComponents > 1 && independentComponents)
1255  {
1256  shaderStr += std::string("\
1257  \n vec4 color[4]; vec4 tmp = vec4(0.0);\
1258  \n float totalAlpha = 0.0;\
1259  \n for (int i = 0; i < in_noOfComponents; ++i)\
1260  \n {\
1261  ");
1262  if (glMapper->GetUseDepthPass() && glMapper->GetCurrentPass() ==
1264  {
1265  shaderStr += std::string("\
1266  \n // Data fetching from the red channel of volume texture\
1267  \n float opacity = computeOpacity(scalar, i);\
1268  \n if (opacity > 0.0)\
1269  \n {\
1270  \n g_srcColor.a = opacity;\
1271  \n }\
1272  \n }"
1273  );
1274  }
1275  else if (!mask || !maskInput ||
1277  {
1278  shaderStr += std::string("\
1279  \n // Data fetching from the red channel of volume texture\
1280  \n color[i][3] = computeOpacity(scalar, i);\
1281  \n color[i] = computeColor(scalar, color[i][3], i);\
1282  \n totalAlpha += color[i][3] * in_componentWeight[i];\
1283  \n }\
1284  \n if (totalAlpha > 0.0)\
1285  \n {\
1286  \n for (int i = 0; i < in_noOfComponents; ++i)\
1287  \n {\
1288  \n // Only let visible components contribute to the final color\
1289  \n if (in_componentWeight[i] <= 0) continue;\
1290  \n\
1291  \n tmp.x += color[i].x * color[i].w * in_componentWeight[i];\
1292  \n tmp.y += color[i].y * color[i].w * in_componentWeight[i];\
1293  \n tmp.z += color[i].z * color[i].w * in_componentWeight[i];\
1294  \n tmp.w += ((color[i].w * color[i].w)/totalAlpha);\
1295  \n }\
1296  \n }\
1297  \n g_fragColor = (1.0f - g_fragColor.a) * tmp + g_fragColor;"
1298  );
1299  }
1300  }
1301  else if (glMapper->GetUseDepthPass() && glMapper->GetCurrentPass() ==
1303  {
1304  shaderStr += std::string("\
1305  \n g_srcColor = vec4(0.0);\
1306  \n g_srcColor.a = computeOpacity(scalar);"
1307  );
1308  }
1309  else
1310  {
1311  if (!mask || !maskInput ||
1313  {
1314  shaderStr += std::string("\
1315  \n g_srcColor = vec4(0.0);\
1316  \n g_srcColor.a = computeOpacity(scalar);\
1317  \n if (g_srcColor.a > 0.0)\
1318  \n {\
1319  \n g_srcColor = computeColor(scalar, g_srcColor.a);"
1320  );
1321  }
1322 
1323  shaderStr += std::string("\
1324  \n // Opacity calculation using compositing:\
1325  \n // Here we use front to back compositing scheme whereby\
1326  \n // the current sample value is multiplied to the\
1327  \n // currently accumulated alpha and then this product\
1328  \n // is subtracted from the sample value to get the\
1329  \n // alpha from the previous steps. Next, this alpha is\
1330  \n // multiplied with the current sample colour\
1331  \n // and accumulated to the composited colour. The alpha\
1332  \n // value from the previous steps is then accumulated\
1333  \n // to the composited colour alpha.\
1334  \n g_srcColor.rgb *= g_srcColor.a;\
1335  \n g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;"
1336  );
1337 
1338  if (!mask || !maskInput ||
1340  {
1341  shaderStr += std::string("\
1342  \n }"
1343  );
1344  }
1345  }
1346  }
1347  else
1348  {
1349  shaderStr += std::string();
1350  }
1351 
1352  shaderStr += std::string("\
1353  \n }"
1354  );
1355  return shaderStr;
1356  }
1357 
1358  //--------------------------------------------------------------------------
1360  vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
1361  {
1362  return std::string("\
1363  \n // Special coloring mode which renders the Prop Id in fragments that\
1364  \n // have accumulated certain level of opacity. Used during the selection\
1365  \n // pass vtkHardwareSelection::ACTOR_PASS.\
1366  \n if (g_fragColor.a > 3.0/ 255.0)\
1367  \n {\
1368  \n gl_FragData[0] = vec4(in_propId, 1.0);\
1369  \n }\
1370  \n else\
1371  \n {\
1372  \n gl_FragData[0] = vec4(0.0);\
1373  \n }\
1374  \n return;");
1375  };
1376 
1377  //--------------------------------------------------------------------------
1379  vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
1380  {
1381  return std::string("\
1382  \n // Special coloring mode which renders the voxel index in fragments that\
1383  \n // have accumulated certain level of opacity. Used during the selection\
1384  \n // pass vtkHardwareSelection::ID_LOW24.\
1385  \n if (g_fragColor.a > 3.0/ 255.0)\
1386  \n {\
1387  \n uvec3 volumeDim = uvec3(in_textureExtentsMax - in_textureExtentsMin);\
1388  \n uvec3 voxelCoords = uvec3(volumeDim * g_dataPos);\
1389  \n // vtkHardwareSelector assumes index 0 to be empty space, so add uint(1).\
1390  \n uint idx = volumeDim.x * volumeDim.y * voxelCoords.z +\
1391  \n volumeDim.x * voxelCoords.y + voxelCoords.x + uint(1);\
1392  \n gl_FragData[0] = vec4(float(idx % uint(256)) / 255.0,\
1393  \n float((idx / uint(256)) % uint(256)) / 255.0,\
1394  \n float((idx / uint(65536)) % uint(256)) / 255.0, 1.0);\
1395  \n }\
1396  \n else\
1397  \n {\
1398  \n gl_FragData[0] = vec4(0.0);\
1399  \n }\
1400  \n return;");
1401  };
1402 
1403  //--------------------------------------------------------------------------
1405  vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
1406  {
1407  return std::string("\
1408  \n // Special coloring mode which renders the voxel index in fragments that\
1409  \n // have accumulated certain level of opacity. Used during the selection\
1410  \n // pass vtkHardwareSelection::ID_MID24.\
1411  \n if (g_fragColor.a > 3.0/ 255.0)\
1412  \n {\
1413  \n uvec3 volumeDim = uvec3(in_textureExtentsMax - in_textureExtentsMin);\
1414  \n uvec3 voxelCoords = uvec3(volumeDim * g_dataPos);\
1415  \n // vtkHardwareSelector assumes index 0 to be empty space, so add uint(1).\
1416  \n uint idx = volumeDim.x * volumeDim.y * voxelCoords.z +\
1417  \n volumeDim.x * voxelCoords.y + voxelCoords.x + uint(1);\
1418  \n idx = ((idx & 0xff000000) >> 24);\
1419  \n gl_FragData[0] = vec4(float(idx % uint(256)) / 255.0,\
1420  \n float((idx / uint(256)) % uint(256)) / 255.0,\
1421  \n float(idx / uint(65536)) / 255.0, 1.0);\
1422  \n }\
1423  \n else\
1424  \n {\
1425  \n gl_FragData[0] = vec4(0.0);\
1426  \n }\
1427  \n return;");
1428  };
1429 
1430  //--------------------------------------------------------------------------
1432  vtkVolumeMapper* mapper,
1433  vtkVolume* vtkNotUsed(vol),
1434  int noOfComponents,
1435  int independentComponents = 0)
1436  {
1439 
1440  if (glMapper->GetUseDepthPass() && glMapper->GetCurrentPass() ==
1443  {
1444  return std::string();
1445  }
1447  {
1448  if (noOfComponents > 1 && independentComponents)
1449  {
1450  return std::string("\
1451  \n g_srcColor = vec4(0);\
1452  \n for (int i = 0; i < in_noOfComponents; ++i)\
1453  \n {\
1454  \n vec4 tmp = computeColor(l_maxValue, computeOpacity(l_maxValue, i), i);\
1455  \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
1456  \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
1457  \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
1458  \n g_srcColor[3] += tmp[3] * in_componentWeight[i];\
1459  \n }\
1460  \n g_fragColor = g_srcColor;"
1461  );
1462  }
1463  else
1464  {
1465  return std::string("\
1466  \n g_srcColor = computeColor(l_maxValue,\
1467  \n computeOpacity(l_maxValue));\
1468  \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
1469  \n g_fragColor.a = g_srcColor.a;"
1470  );
1471  }
1472  }
1474  {
1475  if (noOfComponents > 1 && independentComponents)
1476  {
1477  return std::string("\
1478  \n g_srcColor = vec4(0);\
1479  \n for (int i = 0; i < in_noOfComponents; ++i)\
1480  \n {\
1481  \n vec4 tmp = computeColor(l_minValue, computeOpacity(l_minValue, i), i);\
1482  \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
1483  \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
1484  \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
1485  \n g_srcColor[2] += tmp[3] * tmp[3] * in_componentWeight[i];\
1486  \n }\
1487  \n g_fragColor = g_srcColor;"
1488  );
1489  }
1490  else
1491  {
1492  return std::string("\
1493  \n g_srcColor = computeColor(l_minValue,\
1494  \n computeOpacity(l_minValue));\
1495  \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
1496  \n g_fragColor.a = g_srcColor.a;"
1497  );
1498  }
1499  }
1501  {
1502  if (noOfComponents > 1 && independentComponents)
1503  {
1504  return std::string("\
1505  \n for (int i = 0; i < in_noOfComponents; ++i)\
1506  \n {\
1507  \n if (l_numSamples[i] == uint(0))\
1508  \n {\
1509  \n continue;\
1510  \n }\
1511  \n l_avgValue[i] = l_avgValue[i] * in_componentWeight[i] /\
1512  \n l_numSamples[i];\
1513  \n if (i > 0)\
1514  \n {\
1515  \n l_avgValue[0] += l_avgValue[i];\
1516  \n }\
1517  \n }\
1518  \n l_avgValue[0] = clamp(l_avgValue[0], 0.0, 1.0);\
1519  \n g_fragColor = vec4(vec3(l_avgValue[0]), 1.0);"
1520  );
1521  }
1522  else
1523  {
1524  return std::string("\
1525  \n if (l_numSamples.x == uint(0))\
1526  \n {\
1527  \n discard;\
1528  \n }\
1529  \n else\
1530  \n {\
1531  \n l_avgValue.x /= l_numSamples.x;\
1532  \n l_avgValue.x = clamp(l_avgValue.x, 0.0, 1.0);\
1533  \n g_fragColor = vec4(vec3(l_avgValue.x), 1.0);\
1534  \n }"
1535  );
1536  }
1537  }
1538  else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
1539  {
1540  if (noOfComponents > 1 && independentComponents)
1541  {
1542  // Add all the components to get final color
1543  return std::string("\
1544  \n l_sumValue.x *= in_componentWeight.x;\
1545  \n for (int i = 1; i < in_noOfComponents; ++i)\
1546  \n {\
1547  \n l_sumValue.x += l_sumValue[i] * in_componentWeight[i];\
1548  \n }\
1549  \n l_sumValue.x = clamp(l_sumValue.x, 0.0, 1.0);\
1550  \n g_fragColor = vec4(vec3(l_sumValue.x), 1.0);"
1551  );
1552  }
1553  else
1554  {
1555  return std::string("\
1556  \n l_sumValue.x = clamp(l_sumValue.x, 0.0, 1.0);\
1557  \n g_fragColor = vec4(vec3(l_sumValue.x), 1.0);"
1558  );
1559  }
1560  }
1561  else
1562  {
1563  return std::string();
1564  }
1565  }
1566 
1567  //--------------------------------------------------------------------------
1569  vtkVolumeMapper* vtkNotUsed(mapper),
1570  vtkVolume* vtkNotUsed(vol))
1571  {
1572  return std::string();
1573  }
1574 
1575  //--------------------------------------------------------------------------
1577  vtkVolumeMapper* vtkNotUsed(mapper),
1578  vtkVolume* vtkNotUsed(vol))
1579  {
1580  return std::string("\
1581  \n const float g_opacityThreshold = 1.0 - 1.0 / 255.0;");
1582  }
1583 
1584  //--------------------------------------------------------------------------
1586  vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
1587  {
1588  return std::string("\
1589  \n uniform vec3 in_propId;");
1590  };
1591 
1592  //--------------------------------------------------------------------------
1594  vtkVolumeMapper* vtkNotUsed(mapper),
1595  vtkVolume* vtkNotUsed(vol))
1596  {
1597  return std::string("\
1598  \n // Flag to indicate if the raymarch loop should terminate \
1599  \n bool stop = false;\
1600  \n\
1601  \n g_terminatePointMax = 0.0;\
1602  \n\
1603  \n#ifdef GL_ES\
1604  \n vec4 l_depthValue = vec4(1.0,1.0,1.0,1.0);\
1605  \n#else\
1606  \n vec4 l_depthValue = texture2D(in_depthSampler, fragTexCoord);\
1607  \n#endif\
1608  \n // Depth test\
1609  \n if(gl_FragCoord.z >= l_depthValue.x)\
1610  \n {\
1611  \n discard;\
1612  \n }\
1613  \n\
1614  \n // color buffer or max scalar buffer have a reduced size.\
1615  \n fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
1616  \n in_inverseOriginalWindowSize;\
1617  \n\
1618  \n // Compute max number of iterations it will take before we hit\
1619  \n // the termination point\
1620  \n\
1621  \n // Abscissa of the point on the depth buffer along the ray.\
1622  \n // point in texture coordinates\
1623  \n vec4 terminatePoint = WindowToNDC(gl_FragCoord.x, gl_FragCoord.y, l_depthValue.x);\
1624  \n\
1625  \n // From normalized device coordinates to eye coordinates.\
1626  \n // in_projectionMatrix is inversed because of way VT\
1627  \n // From eye coordinates to texture coordinates\
1628  \n terminatePoint = ip_inverseTextureDataAdjusted *\
1629  \n in_inverseVolumeMatrix *\
1630  \n in_inverseModelViewMatrix *\
1631  \n in_inverseProjectionMatrix *\
1632  \n terminatePoint;\
1633  \n terminatePoint /= terminatePoint.w;\
1634  \n\
1635  \n g_terminatePointMax = length(terminatePoint.xyz - g_dataPos.xyz) /\
1636  \n length(g_dirStep);\
1637  \n g_currentT = 0.0;");
1638  }
1639 
1640  //--------------------------------------------------------------------------
1642  vtkVolumeMapper* vtkNotUsed(mapper),
1643  vtkVolume* vtkNotUsed(vol))
1644  {
1645  return std::string("\
1646  \n if(any(greaterThan(g_dataPos, in_texMax)) ||\
1647  \n any(lessThan(g_dataPos, in_texMin)))\
1648  \n {\
1649  \n break;\
1650  \n }\
1651  \n\
1652  \n // Early ray termination\
1653  \n // if the currently composited colour alpha is already fully saturated\
1654  \n // we terminated the loop or if we have hit an obstacle in the\
1655  \n // direction of they ray (using depth buffer) we terminate as well.\
1656  \n if((g_fragColor.a > g_opacityThreshold) || \
1657  \n g_currentT >= g_terminatePointMax)\
1658  \n {\
1659  \n break;\
1660  \n }\
1661  \n ++g_currentT;"
1662  );
1663  }
1664 
1665  //--------------------------------------------------------------------------
1667  vtkVolumeMapper* vtkNotUsed(mapper),
1668  vtkVolume* vtkNotUsed(vol))
1669  {
1670  return std::string();
1671  }
1672 
1673  //--------------------------------------------------------------------------
1675  vtkVolumeMapper* vtkNotUsed(mapper),
1676  vtkVolume* vtkNotUsed(vol))
1677  {
1678  return std::string();
1679  }
1680 
1681  //--------------------------------------------------------------------------
1683  vtkVolumeMapper* mapper,
1684  vtkVolume* vtkNotUsed(vol))
1685  {
1686  if (!mapper->GetCropping()) {
1687  return std::string();
1688  }
1689 
1690  return std::string("\
1691  \nuniform float in_croppingPlanes[6];\
1692  \nuniform int in_croppingFlags [32];\
1693  \nfloat croppingPlanesTexture[6];\
1694  \n\
1695  \n// X: axis = 0, Y: axis = 1, Z: axis = 2\
1696  \n// cp Cropping plane bounds (minX, maxX, minY, maxY, minZ, maxZ)\
1697  \nint computeRegionCoord(float cp[6], vec3 pos, int axis)\
1698  \n {\
1699  \n int cpmin = axis * 2;\
1700  \n int cpmax = cpmin + 1;\
1701  \n\
1702  \n if (pos[axis] < cp[cpmin])\
1703  \n {\
1704  \n return 1;\
1705  \n }\
1706  \n else if (pos[axis] >= cp[cpmin] &&\
1707  \n pos[axis] < cp[cpmax])\
1708  \n {\
1709  \n return 2;\
1710  \n }\
1711  \n else if (pos[axis] >= cp[cpmax])\
1712  \n {\
1713  \n return 3;\
1714  \n }\
1715  \n return 0;\
1716  \n }\
1717  \n\
1718  \nint computeRegion(float cp[6], vec3 pos)\
1719  \n {\
1720  \n return (computeRegionCoord(cp, pos, 0) +\
1721  \n (computeRegionCoord(cp, pos, 1) - 1) * 3 +\
1722  \n (computeRegionCoord(cp, pos, 2) - 1) * 9);\
1723  \n }"
1724  );
1725  }
1726 
1727  //--------------------------------------------------------------------------
1729  vtkVolumeMapper* mapper,
1730  vtkVolume* vtkNotUsed(vol))
1731  {
1732  if (!mapper->GetCropping()) {
1733  return std::string();
1734  }
1735 
1736  return std::string("\
1737  \n // Convert cropping region to texture space\
1738  \n mat4 datasetToTextureMat = in_inverseTextureDatasetMatrix;\
1739  \n\
1740  \n vec4 tempCrop = vec4(in_croppingPlanes[0], 0.0, 0.0, 1.0);\
1741  \n tempCrop = datasetToTextureMat * tempCrop;\
1742  \n if (tempCrop[3] != 0.0)\
1743  \n {\
1744  \n tempCrop[0] /= tempCrop[3];\
1745  \n }\
1746  \n croppingPlanesTexture[0] = tempCrop[0];\
1747  \n\
1748  \n tempCrop = vec4(in_croppingPlanes[1], 0.0, 0.0, 1.0);\
1749  \n tempCrop = datasetToTextureMat * tempCrop;\
1750  \n if (tempCrop[3] != 0.0)\
1751  \n {\
1752  \n tempCrop[0] /= tempCrop[3];\
1753  \n }\
1754  \n croppingPlanesTexture[1] = tempCrop[0];\
1755  \n\
1756  \n tempCrop = vec4(0.0, in_croppingPlanes[2], 0.0, 1.0);\
1757  \n tempCrop = datasetToTextureMat * tempCrop;\
1758  \n if (tempCrop[3] != 0.0)\
1759  \n {\
1760  \n tempCrop[1] /= tempCrop[3];\
1761  \n }\
1762  \n croppingPlanesTexture[2] = tempCrop[1];\
1763  \n\
1764  \n tempCrop = vec4(0.0, in_croppingPlanes[3], 0.0, 1.0);\
1765  \n tempCrop = datasetToTextureMat * tempCrop;\
1766  \n if (tempCrop[3] != 0.0)\
1767  \n {\
1768  \n tempCrop[1] /= tempCrop[3];\
1769  \n }\
1770  \n croppingPlanesTexture[3] = tempCrop[1];\
1771  \n\
1772  \n tempCrop = vec4(0.0, 0.0, in_croppingPlanes[4], 1.0);\
1773  \n tempCrop = datasetToTextureMat * tempCrop;\
1774  \n if (tempCrop[3] != 0.0)\
1775  \n {\
1776  \n tempCrop[2] /= tempCrop[3];\
1777  \n }\
1778  \n croppingPlanesTexture[4] = tempCrop[2];\
1779  \n\
1780  \n tempCrop = vec4(0.0, 0.0, in_croppingPlanes[5], 1.0);\
1781  \n tempCrop = datasetToTextureMat * tempCrop;\
1782  \n if (tempCrop[3] != 0.0)\
1783  \n {\
1784  \n tempCrop[2] /= tempCrop[3];\
1785  \n }\
1786  \n croppingPlanesTexture[5] = tempCrop[2];"
1787  );
1788  }
1789 
1790  //--------------------------------------------------------------------------
1792  vtkVolumeMapper* mapper,
1793  vtkVolume* vtkNotUsed(vol))
1794  {
1795  if (!mapper->GetCropping()) {
1796  return std::string();
1797  }
1798 
1799  return std::string("\
1800  \n // Determine region\
1801  \n int regionNo = computeRegion(croppingPlanesTexture, g_dataPos);\
1802  \n\
1803  \n // Do & operation with cropping flags\
1804  \n // Pass the flag that its Ok to sample or not to sample\
1805  \n if (in_croppingFlags[regionNo] == 0)\
1806  \n {\
1807  \n // Skip this voxel\
1808  \n g_skip = true;\
1809  \n }"
1810  );
1811  }
1812 
1813  //--------------------------------------------------------------------------
1815  vtkVolumeMapper* vtkNotUsed(mapper),
1816  vtkVolume* vtkNotUsed(vol))
1817  {
1818  return std::string();
1819  }
1820 
1821  //--------------------------------------------------------------------------
1823  vtkVolumeMapper* vtkNotUsed(mapper),
1824  vtkVolume* vtkNotUsed(vol))
1825  {
1826  return std::string();
1827  }
1828 
1829  //--------------------------------------------------------------------------
1831  vtkVolumeMapper* vtkNotUsed(mapper),
1832  vtkVolume* vtkNotUsed(vol))
1833  {
1834  return std::string("\
1835  \n int clippingPlanesSize;\
1836  \n vec3 objRayDir;\
1837  \n mat4 textureToObjMat;");
1838  }
1839 
1840  //--------------------------------------------------------------------------
1842  vtkVolumeMapper* mapper,
1843  vtkVolume* vtkNotUsed(vol))
1844  {
1845  if (!mapper->GetClippingPlanes())
1846  {
1847  return std::string();
1848  }
1849 
1850  std::string shaderStr;
1851  if (!ren->GetActiveCamera()->GetParallelProjection())
1852  {
1853  shaderStr = std::string("\
1854  vec4 tempClip = in_volumeMatrix * vec4(rayDir, 0.0);\
1855  \n if (tempClip.w != 0.0)\
1856  \n {\
1857  \n tempClip = tempClip/tempClip.w;\
1858  \n tempClip.w = 1.0;\
1859  \n }\
1860  \n objRayDir = tempClip.xyz;");
1861  }
1862  else
1863  {
1864  shaderStr = std::string("\
1865  objRayDir = normalize(in_projectionDirection);");
1866  }
1867 
1868  shaderStr += std::string("\
1869  \n clippingPlanesSize = int(in_clippingPlanes[0]);\
1870  \n vec4 objDataPos = vec4(0.0);\
1871  \n textureToObjMat = in_volumeMatrix * in_textureDatasetMatrix;\
1872  \n\
1873  \n vec4 terminatePointObj = textureToObjMat * terminatePoint;\
1874  \n if (terminatePointObj.w != 0.0)\
1875  \n {\
1876  \n terminatePointObj = terminatePointObj/ terminatePointObj.w ;\
1877  \n terminatePointObj.w = 1.0;\
1878  \n }\
1879  \n\
1880  \n for (int i = 0; i < clippingPlanesSize; i = i + 6)\
1881  \n {\
1882  \n if (in_useJittering)\
1883  \n {\
1884  \n objDataPos = textureToObjMat * vec4(g_dataPos - g_rayJitter,\
1885  \n 1.0);\
1886  \n }\
1887  \n else\
1888  \n {\
1889  \n objDataPos = textureToObjMat * vec4(g_dataPos - g_dirStep, 1.0);\
1890  \n }\
1891  \n if (objDataPos.w != 0.0)\
1892  \n {\
1893  \n objDataPos = objDataPos/objDataPos.w; objDataPos.w = 1.0;\
1894  \n }\
1895  \n vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\
1896  \n in_clippingPlanes[i + 2],\
1897  \n in_clippingPlanes[i + 3]);\
1898  \n vec3 planeNormal = vec3(in_clippingPlanes[i + 4],\
1899  \n in_clippingPlanes[i + 5],\
1900  \n in_clippingPlanes[i + 6]);\
1901  \n vec3 normalizedPlaneNormal = normalize(planeNormal);\
1902  \n\
1903  \n float rayDotNormal = dot(objRayDir, normalizedPlaneNormal);\
1904  \n bool frontFace = rayDotNormal > 0;\
1905  \n float distance = dot(normalizedPlaneNormal, planeOrigin - objDataPos.xyz);\
1906  \n\
1907  \n if (frontFace && // Observing from the clipped side (plane's front face)\
1908  \n distance > 0.0) // Ray-entry lies on the clipped side.\
1909  \n {\
1910  \n // Scale the point-plane distance to the ray direction and update the\
1911  \n // entry point.\
1912  \n float rayScaledDist = distance / rayDotNormal;\
1913  \n vec4 newObjDataPos = vec4(objDataPos.xyz + rayScaledDist * objRayDir, 1.0);\
1914  \n newObjDataPos = in_inverseTextureDatasetMatrix\
1915  \n * in_inverseVolumeMatrix * vec4(newObjDataPos.xyz, 1.0);\
1916  \n if (newObjDataPos.w != 0.0)\
1917  \n {\
1918  \n newObjDataPos /= newObjDataPos.w;\
1919  \n }\
1920  \n if (in_useJittering)\
1921  \n {\
1922  \n g_dataPos = newObjDataPos.xyz + g_rayJitter;\
1923  \n }\
1924  \n else\
1925  \n {\
1926  \n g_dataPos = newObjDataPos.xyz + g_dirStep;\
1927  \n }\
1928  \n\
1929  \n bool stop = any(greaterThan(g_dataPos, in_texMax)) ||\
1930  \n any(lessThan(g_dataPos, in_texMin));\
1931  \n if (stop)\
1932  \n {\
1933  \n // The ray exits the bounding box before ever intersecting the plane (only\
1934  \n // the clipped space is hit).\
1935  \n discard;\
1936  \n }\
1937  \n\
1938  \n bool behindGeometry = dot(terminatePointObj.xyz - planeOrigin.xyz, normalizedPlaneNormal) < 0.0;\
1939  \n if (behindGeometry)\
1940  \n {\
1941  \n // Geometry appears in front of the plane.\
1942  \n discard;\
1943  \n }\
1944  \n\
1945  \n // Update the number of ray marching steps to account for the clipped entry point (\
1946  \n // this is necessary in case the ray hits geometry after marching behind the plane,\
1947  \n // given that the number of steps was assumed to be from the not-clipped entry).\
1948  \n g_terminatePointMax = length(terminatePoint.xyz - g_dataPos.xyz) /\
1949  \n length(g_dirStep);\
1950  \n }\
1951  \n }");
1952 
1953  return shaderStr;
1954  }
1955 
1956  //--------------------------------------------------------------------------
1958  vtkVolumeMapper* mapper,
1959  vtkVolume* vtkNotUsed(vol))
1960  {
1961  if (!mapper->GetClippingPlanes())
1962  {
1963  return std::string();
1964  }
1965  else
1966  {
1967  return std::string("\
1968  \n for (int i = 0; i < clippingPlanesSize && !g_skip; i = i + 6)\
1969  \n {\
1970  \n vec4 objDataPos = textureToObjMat * vec4(g_dataPos, 1.0);\
1971  \n if (objDataPos.w != 0.0)\
1972  \n {\
1973  \n objDataPos /= objDataPos.w;\
1974  \n }\
1975  \n vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\
1976  \n in_clippingPlanes[i + 2],\
1977  \n in_clippingPlanes[i + 3]);\
1978  \n vec3 planeNormal = vec3(in_clippingPlanes[i + 4],\
1979  \n in_clippingPlanes[i + 5],\
1980  \n in_clippingPlanes[i + 6]);\
1981  \n if (dot(vec3(objDataPos.xyz - planeOrigin), planeNormal) < 0 && dot(objRayDir, planeNormal) < 0)\
1982  \n {\
1983  \n g_skip = true;\
1984  \n g_exit = true;\
1985  \n }\
1986  \n }"
1987  );
1988  }
1989  }
1990 
1991  //--------------------------------------------------------------------------
1993  vtkVolumeMapper* vtkNotUsed(mapper),
1994  vtkVolume* vtkNotUsed(vol))
1995  {
1996  return std::string();
1997  }
1998 
1999  //--------------------------------------------------------------------------
2001  vtkVolumeMapper* vtkNotUsed(mapper),
2002  vtkVolume* vtkNotUsed(vol),
2003  vtkImageData* maskInput,
2004  vtkVolumeMask* mask,
2005  int vtkNotUsed(maskType))
2006  {
2007  if (!mask || !maskInput)
2008  {
2009  return std::string();
2010  }
2011  else
2012  {
2013  return std::string("uniform sampler3D in_mask;");
2014  }
2015  }
2016 
2017  //--------------------------------------------------------------------------
2019  vtkVolumeMapper* vtkNotUsed(mapper),
2020  vtkVolume* vtkNotUsed(vol),
2021  vtkImageData* maskInput,
2022  vtkVolumeMask* mask,
2023  int maskType)
2024  {
2025  if (!mask || !maskInput ||
2027  {
2028  return std::string();
2029  }
2030  else
2031  {
2032  return std::string("\
2033  \nvec4 maskValue = texture3D(in_mask, g_dataPos);\
2034  \nif(maskValue.r <= 0.0)\
2035  \n {\
2036  \n g_skip = true;\
2037  \n }"
2038  );
2039  }
2040  }
2041 
2042  //--------------------------------------------------------------------------
2044  vtkVolumeMapper* vtkNotUsed(mapper),
2045  vtkVolume* vtkNotUsed(vol),
2046  vtkImageData* maskInput,
2047  vtkVolumeMask* mask,
2048  int maskType)
2049  {
2050  if (!mask || !maskInput ||
2052  {
2053  return std::string();
2054  }
2055  else
2056  {
2057  return std::string("\
2058  \nuniform float in_maskBlendFactor;\
2059  \nuniform sampler2D in_mask1;\
2060  \nuniform sampler2D in_mask2;"
2061  );
2062  }
2063  }
2064 
2065  //--------------------------------------------------------------------------
2067  vtkVolumeMapper* vtkNotUsed(mapper),
2068  vtkVolume* vtkNotUsed(vol),
2069  vtkImageData* maskInput,
2070  vtkVolumeMask* mask,
2071  int maskType,
2072  int noOfComponents)
2073  {
2074  if (!mask || !maskInput ||
2076  {
2077  return std::string();
2078  }
2079  else
2080  {
2081  std::string shaderStr = std::string("\
2082  \nvec4 scalar = texture3D(in_volume, g_dataPos);");
2083 
2084  // simulate old intensity textures
2085  if (noOfComponents == 1)
2086  {
2087  shaderStr += std::string("\
2088  \n scalar.r = scalar.r*in_volume_scale.r + in_volume_bias.r;\
2089  \n scalar = vec4(scalar.r,scalar.r,scalar.r,scalar.r);"
2090  );
2091  }
2092  else
2093  {
2094  // handle bias and scale
2095  shaderStr += std::string("\
2096  \n scalar = scalar*in_volume_scale + in_volume_bias;"
2097  );
2098  }
2099 
2100  return shaderStr + std::string("\
2101  \nif (in_maskBlendFactor == 0.0)\
2102  \n {\
2103  \n g_srcColor = computeColor(scalar, computeOpacity(scalar));\
2104  \n }\
2105  \nelse\
2106  \n {\
2107  \n float opacity = computeOpacity(scalar);\
2108  \n // Get the mask value at this same location\
2109  \n vec4 maskValue = texture3D(in_mask, g_dataPos);\
2110  \n if(maskValue.r == 0.0)\
2111  \n {\
2112  \n g_srcColor = computeColor(scalar, opacity);\
2113  \n }\
2114  \n else\
2115  \n {\
2116  \n if (maskValue.r == 1.0/255.0)\
2117  \n {\
2118  \n g_srcColor = texture2D(in_mask1, vec2(scalar.w,0.0));\
2119  \n }\
2120  \n else\
2121  \n {\
2122  \n // maskValue.r == 2.0/255.0\
2123  \n g_srcColor = texture2D(in_mask2, vec2(scalar.w,0.0));\
2124  \n }\
2125  \n g_srcColor.a = 1.0;\
2126  \n if(in_maskBlendFactor < 1.0)\
2127  \n {\
2128  \n g_srcColor = (1.0 - in_maskBlendFactor) *\
2129  \n computeColor(scalar, opacity) +\
2130  \n in_maskBlendFactor * g_srcColor;\
2131  \n }\
2132  \n }\
2133  \n g_srcColor.a = opacity;\
2134  \n }"
2135  );
2136  }
2137  }
2138 
2139  //--------------------------------------------------------------------------
2141  vtkVolumeMapper* vtkNotUsed(mapper),
2142  vtkVolume* vtkNotUsed(vol))
2143  {
2144  return std::string("\
2145  \n vec3 l_opaqueFragPos;\
2146  \n bool l_updateDepth;");
2147  }
2148 
2149  //--------------------------------------------------------------------------
2151  vtkVolumeMapper* vtkNotUsed(mapper),
2152  vtkVolume* vtkNotUsed(vol))
2153  {
2154  return std::string("\
2155  \n l_opaqueFragPos = vec3(-1.0);\
2156  \n if(in_clampDepthToBackface)\
2157  \n {\
2158  \n l_opaqueFragPos = g_dataPos;\
2159  \n }\
2160  \n l_updateDepth = true;"
2161  );
2162  }
2163 
2164  //--------------------------------------------------------------------------
2166  vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper),
2167  vtkVolume* vtkNotUsed(vol))
2168  {
2169  return std::string("\
2170  \n if(!g_skip && g_srcColor.a > 0.0 && l_updateDepth)\
2171  \n {\
2172  \n l_opaqueFragPos = g_dataPos;\
2173  \n l_updateDepth = false;\
2174  \n }"
2175  );
2176  }
2177 
2178  //--------------------------------------------------------------------------
2180  vtkVolumeMapper* vtkNotUsed(mapper),
2181  vtkVolume* vtkNotUsed(vol))
2182  {
2183  return std::string("\
2184  \n if (l_opaqueFragPos == vec3(-1.0))\
2185  \n {\
2186  \n gl_FragData[1] = vec4(1.0);\
2187  \n }\
2188  \n else\
2189  \n {\
2190  \n vec4 depthValue = in_projectionMatrix * in_modelViewMatrix *\
2191  \n in_volumeMatrix * in_textureDatasetMatrix *\
2192  \n vec4(l_opaqueFragPos, 1.0);\
2193  \n depthValue /= depthValue.w;\
2194  \n gl_FragData[1] = vec4(vec3(0.5 * (gl_DepthRange.far -\
2195  \n gl_DepthRange.near) * depthValue.z + 0.5 *\
2196  \n (gl_DepthRange.far + gl_DepthRange.near)), 1.0);\
2197  \n }"
2198  );
2199  }
2200 
2201  //--------------------------------------------------------------------------
2203  vtkVolumeMapper* vtkNotUsed(mapper),
2204  vtkVolume* vtkNotUsed(vol))
2205  {
2206  return std::string("\
2207  \n vec3 l_isoPos = g_dataPos;"
2208  );
2209  }
2210 
2211  //--------------------------------------------------------------------------
2213  vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper),
2214  vtkVolume* vtkNotUsed(vol))
2215  {
2216  return std::string("\
2217  \n if(!g_skip && g_srcColor.a > 0.0)\
2218  \n {\
2219  \n l_isoPos = g_dataPos;\
2220  \n g_exit = true; g_skip = true;\
2221  \n }"
2222  );
2223  }
2224 
2225  //--------------------------------------------------------------------------
2227  vtkVolumeMapper* vtkNotUsed(mapper),
2228  vtkVolume* vtkNotUsed(vol))
2229  {
2230  return std::string("\
2231  \n vec4 depthValue = in_projectionMatrix * in_modelViewMatrix *\
2232  \n in_volumeMatrix * in_textureDatasetMatrix *\
2233  \n vec4(l_isoPos, 1.0);\
2234  \n gl_FragData[0] = vec4(l_isoPos, 1.0);\
2235  \n gl_FragData[1] = vec4(vec3((depthValue.z/depthValue.w) * 0.5 + 0.5),\
2236  \n 1.0);"
2237  );
2238  }
2239 
2240  //---------------------------------------------------------------------------
2242  vtkVolumeMapper* vtkNotUsed(mapper),
2243  vtkVolume* vtkNotUsed(vol))
2244  {
2245  return std::string("\
2246  \n initializeRayCast();\
2247  \n castRay(-1.0, -1.0);\
2248  \n finalizeRayCast();");
2249  }
2250 }
2251 
2252 #endif // vtkVolumeShaderComposer_h
2253 // 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 &amp; properties) in a rendered scene
Definition: vtkVolume.h:44
std::string CroppingDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string CompositeMaskImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeMask *mask, int maskType, int noOfComponents)
Abstract class for a volume mapper.
std::string BinaryMaskDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeMask *mask, int vtkNotUsed(maskType))
virtual int GetUseDepthPass()
If UseDepthPass is on, the mapper will use two passes.
std::string DepthPassInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
virtual int GetBlendMode()
Set/Get the blend mode.
std::string PickingActorPassDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string RenderToImageDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
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 BinaryMaskImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeMask *mask, int maskType)
std::string replace(std::string source, const std::string &search, const std::string &replace, bool all)
virtual vtkPlaneCollection * GetClippingPlanes()
Get/Set the vtkPlaneCollection which specifies the clipping planes.
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 subclass that draws the image to the screen.
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 ClippingExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string CompositeMaskDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeMask *mask, int maskType)
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 ShadingImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeMask *mask, int maskType, int noOfComponents, int independentComponents=0)
std::string WorkerImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
virtual int GetParallelProjection()
Set/Get the value of the ParallelProjection instance variable.
std::string ComputeClipPositionImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ComputeRayDirectionDeclaration(vtkRenderer *ren, vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int vtkNotUsed(noOfComponents))
std::string ShadingInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
represents the common properties for rendering a volume.
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 ComputeTextureCoordinates(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
boost::graph_traits< vtkGraph * >::vertex_descriptor source(boost::graph_traits< vtkGraph * >::edge_descriptor e, vtkGraph *)
std::string ComputeGradientDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vol, int noOfComponents, int independentComponents, std::map< int, std::string > gradientTableMap)
std::string PickingIdLow24PassExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string CroppingInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
vtkVolumeProperty * GetProperty()
Set/Get the volume property.
virtual int GetCropping()
Turn On/Off orthogonal cropping.
std::string TerminationDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string BaseDeclarationVertex(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 BaseInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vol, int lightingComplexity)
std::string BaseDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), int vtkNotUsed(numberOfLights), int lightingComplexity, bool hasGradientOpacity, int noOfComponents, int independentComponents)
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))