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>
22 #include <vtkRenderer.h>
23 #include <vtkVolume.h>
24 #include <vtkVolumeMapper.h>
25 #include <vtkVolumeProperty.h>
26 
27 #include <map>
28 #include <sstream>
29 #include <string>
30 
31 namespace vtkvolume
32 {
33  //--------------------------------------------------------------------------
35  const std::string replace, bool all)
36  {
37  if (replace.empty())
38  {
39  return source;
40  }
41 
42  std::string::size_type pos = 0;
43  bool first = true;
44  while ((pos = source.find(search, 0)) != std::string::npos)
45  {
46  source.replace(pos, search.length(), replace);
47  pos += search.length();
48  if (first)
49  {
50  first = false;
51  if (!all)
52  {
53  return source;
54  }
55  }
56  }
57  return source;
58  }
59 
60  //--------------------------------------------------------------------------
62  vtkVolumeMapper* vtkNotUsed(mapper),
63  vtkVolume* vtkNotUsed(vol))
64  {
65  return std::string("\
66  \n vec4 pos = in_projectionMatrix * in_modelViewMatrix *\
67  \n in_volumeMatrix * vec4(in_vertexPos.xyz, 1.0);\
68  \n gl_Position = pos;"
69  );
70  }
71 
72  //--------------------------------------------------------------------------
74  vtkVolumeMapper* vtkNotUsed(mapper),
75  vtkVolume* vtkNotUsed(vol))
76  {
77  return std::string(
78  "\n // Assuming point data only. Also, we offset the texture coordinate\
79  \n // to account for OpenGL treating voxel at the center of the cell.\
80  \n vec3 uvx = (in_vertexPos - in_volumeExtentsMin) /\
81  \n (in_volumeExtentsMax - in_volumeExtentsMin);\
82  \n vec3 delta = in_textureExtentsMax - in_textureExtentsMin;\
83  \n ip_textureCoords = (uvx * (delta - vec3(1.0)) + vec3(0.5)) / delta;"
84  );
85  }
86 
87  //--------------------------------------------------------------------------
89  vtkVolumeMapper* vtkNotUsed(mapper),
90  vtkVolume* vtkNotUsed(vol))
91  {
92  return std::string("\
93  \n uniform mat4 in_modelViewMatrix;\
94  \n uniform mat4 in_projectionMatrix;\
95  \n uniform mat4 in_volumeMatrix;\
96  \n\
97  \n uniform vec3 in_volumeExtentsMin;\
98  \n uniform vec3 in_volumeExtentsMax;\
99  \n\
100  \n uniform vec3 in_textureExtentsMax;\
101  \n uniform vec3 in_textureExtentsMin;"
102  );
103  }
104 
105  //--------------------------------------------------------------------------
107  vtkVolumeMapper* vtkNotUsed(mapper),
108  vtkVolume* vtkNotUsed(vol),
109  int vtkNotUsed(numberOfLights),
110  int lightingComplexity,
111  int noOfComponents,
112  int independentComponents)
113  {
114  std::string shaderStr = std::string("\
115  \n// Volume dataset\
116  \nuniform sampler3D in_volume;\
117  \nuniform int in_noOfComponents;\
118  \nuniform int in_independentComponents;\
119  \n\
120  \nuniform sampler2D in_noiseSampler;\
121  \nuniform sampler2D in_depthSampler;\
122  \n\
123  \n// Camera position\
124  \nuniform vec3 in_cameraPos;\
125  \n\
126  \n// view and model matrices\
127  \nuniform mat4 in_volumeMatrix;\
128  \nuniform mat4 in_inverseVolumeMatrix;\
129  \nuniform mat4 in_projectionMatrix;\
130  \nuniform mat4 in_inverseProjectionMatrix;\
131  \nuniform mat4 in_modelViewMatrix;\
132  \nuniform mat4 in_inverseModelViewMatrix;\
133  \nuniform mat4 in_textureDatasetMatrix;\
134  \nuniform mat4 in_inverseTextureDatasetMatrix;\
135  \nuniform mat3 in_texureToEyeIt;\
136  \n\
137  \n// Ray step size\
138  \nuniform vec3 in_cellStep;\
139  \nuniform vec2 in_scalarsRange;\
140  \nuniform vec3 in_cellSpacing;\
141  \n\
142  \n// Sample distance\
143  \nuniform float in_sampleDistance;\
144  \n\
145  \n// Scales\
146  \nuniform vec3 in_cellScale;\
147  \nuniform vec2 in_windowLowerLeftCorner;\
148  \nuniform vec2 in_inverseOriginalWindowSize;\
149  \nuniform vec2 in_inverseWindowSize;\
150  \nuniform vec3 in_textureExtentsMax;\
151  \nuniform vec3 in_textureExtentsMin;\
152  \n\
153  \n// Material and lighting\
154  \nuniform vec3 in_diffuse;\
155  \nuniform vec3 in_ambient;\
156  \nuniform vec3 in_specular;\
157  \nuniform float in_shininess;\
158  ");
159 
160  if (lightingComplexity > 0)
161  {
162  shaderStr += std::string("\
163  \nuniform bool in_twoSidedLighting;\
164  \nvec3 g_xvec;\
165  \nvec3 g_yvec;\
166  \nvec3 g_zvec;\
167  \nvec3 g_cellSpacing;\
168  \nfloat g_avgSpacing;"
169  );
170  }
171 
172  if (lightingComplexity == 3)
173  {
174  shaderStr += std::string("\
175  \nvec4 g_fragWorldPos;\
176  \nuniform int in_numberOfLights;\
177  \nuniform vec3 in_lightAmbientColor[6];\
178  \nuniform vec3 in_lightDiffuseColor[6];\
179  \nuniform vec3 in_lightSpecularColor[6];\
180  \nuniform vec3 in_lightDirection[6];\
181  \nuniform vec3 in_lightPosition[6];\
182  \nuniform vec3 in_lightAttenuation[6];\
183  \nuniform float in_lightConeAngle[6];\
184  \nuniform float in_lightExponent[6];\
185  \nuniform int in_lightPositional[6];\
186  ");
187  }
188  else if (lightingComplexity == 2)
189  {
190  shaderStr += std::string("\
191  \nvec4 g_fragWorldPos;\
192  \nuniform int in_numberOfLights;\
193  \nuniform vec3 in_lightAmbientColor[6];\
194  \nuniform vec3 in_lightDiffuseColor[6];\
195  \nuniform vec3 in_lightSpecularColor[6];\
196  \nuniform vec3 in_lightDirection[6];\
197  ");
198  }
199  else
200  {
201  shaderStr += std::string("\
202  \nuniform vec3 in_lightAmbientColor[1];\
203  \nuniform vec3 in_lightDiffuseColor[1];\
204  \nuniform vec3 in_lightSpecularColor[1];\
205  \nvec4 g_lightPosObj;\
206  \nvec3 g_ldir;\
207  \nvec3 g_vdir;\
208  \nvec3 g_h;\
209  \nvec3 g_aspect;"
210  );
211  }
212 
213  if (noOfComponents > 1 && independentComponents)
214  {
215  shaderStr += std::string("\
216  \nuniform vec4 in_componentWeight;");
217  }
218 
219  return shaderStr;
220  }
221 
222  //--------------------------------------------------------------------------
223  std::string BaseInit(vtkRenderer* vtkNotUsed(ren),
224  vtkVolumeMapper* vtkNotUsed(mapper),
225  vtkVolume* vol,
226  int lightingComplexity)
227  {
228  std::string shaderStr = std::string("\
229  \n // Get the 3D texture coordinates for lookup into the in_volume dataset\
230  \n g_dataPos = ip_textureCoords.xyz;\
231  \n\
232  \n // Eye position in object space\
233  \n g_eyePosObj = (in_inverseVolumeMatrix * vec4(in_cameraPos, 1.0));\
234  \n if (g_eyePosObj.w != 0.0)\
235  \n {\
236  \n g_eyePosObj.x /= g_eyePosObj.w;\
237  \n g_eyePosObj.y /= g_eyePosObj.w;\
238  \n g_eyePosObj.z /= g_eyePosObj.w;\
239  \n g_eyePosObj.w = 1.0;\
240  \n }\
241  \n\
242  \n // Getting the ray marching direction (in object space);\
243  \n vec3 rayDir = computeRayDirection();\
244  \n\
245  \n // Multiply the raymarching direction with the step size to get the\
246  \n // sub-step size we need to take at each raymarching step\
247  \n g_dirStep = (in_inverseTextureDatasetMatrix *\
248  \n vec4(rayDir, 0.0)).xyz * in_sampleDistance;\
249  \n\
250  \n g_dataPos += g_dirStep * (texture2D(in_noiseSampler, g_dataPos.xy).x);\
251  \n\
252  \n // Flag to deternmine if voxel should be considered for the rendering\
253  \n bool l_skip = false;");
254 
255  if (vol->GetProperty()->GetShade() && lightingComplexity == 1)
256  {
257  shaderStr += std::string("\
258  \n // Light position in object space\
259  \n g_lightPosObj = (in_inverseVolumeMatrix *\
260  \n vec4(in_cameraPos, 1.0));\
261  \n if (g_lightPosObj.w != 0.0)\
262  \n {\
263  \n g_lightPosObj.x /= g_lightPosObj.w;\
264  \n g_lightPosObj.y /= g_lightPosObj.w;\
265  \n g_lightPosObj.z /= g_lightPosObj.w;\
266  \n g_lightPosObj.w = 1.0;\
267  \n }\
268  \n g_ldir = normalize(g_lightPosObj.xyz - ip_vertexPos);\
269  \n g_vdir = normalize(g_eyePosObj.xyz - ip_vertexPos);\
270  \n g_h = normalize(g_ldir + g_vdir);\
271  \n g_cellSpacing = vec3(in_cellSpacing[0],\
272  \n in_cellSpacing[1],\
273  \n in_cellSpacing[2]);\
274  \n g_avgSpacing = (g_cellSpacing[0] +\
275  \n g_cellSpacing[1] +\
276  \n g_cellSpacing[2])/3.0;\
277  \n // Adjust the aspect\
278  \n g_aspect.x = g_cellSpacing[0] * 2.0 / g_avgSpacing;\
279  \n g_aspect.y = g_cellSpacing[1] * 2.0 / g_avgSpacing;\
280  \n g_aspect.z = g_cellSpacing[2] * 2.0 / g_avgSpacing;"
281  );
282  }
283  if (vol->GetProperty()->GetShade())
284  {
285  shaderStr += std::string("\
286  \n g_xvec = vec3(in_cellStep[0], 0.0, 0.0);\
287  \n g_yvec = vec3(0.0, in_cellStep[1], 0.0);\
288  \n g_zvec = vec3(0.0, 0.0, in_cellStep[2]);"
289  );
290  }
291  return shaderStr;
292  }
293 
294  //--------------------------------------------------------------------------
296  vtkVolumeMapper* vtkNotUsed(mapper),
297  vtkVolume* vtkNotUsed(vol))
298  {
299  return std::string("\
300  \n l_skip = false;"
301  );
302  }
303 
304  //--------------------------------------------------------------------------
305  std::string BaseExit(vtkRenderer* vtkNotUsed(ren),
306  vtkVolumeMapper* vtkNotUsed(mapper),
307  vtkVolume* vtkNotUsed(vol))
308  {
309  return std::string();
310  }
311 
312  //--------------------------------------------------------------------------
314  vtkVolumeMapper* vtkNotUsed(mapper),
315  vtkVolume* vol,
316  int noOfComponents,
317  int independentComponents,
318  std::map<int, std::string> gradientTableMap)
319  {
320  std::string shaderStr;
321  if (noOfComponents == 1 && vol->GetProperty()->HasGradientOpacity())
322  {
323  shaderStr += std::string("\
324  \nuniform sampler1D in_gradientTransferFunc;\
325  \nfloat computeGradientOpacity(vec4 grad)\
326  \n {\
327  \n return texture1D(in_gradientTransferFunc, grad.w).r;\
328  \n }"
329  );
330  }
331  else if (noOfComponents > 1 && independentComponents &&
333  {
334  for (int i = 0; i < noOfComponents; ++i)
335  {
336  shaderStr += std::string("\n uniform sampler1D ") +
337  gradientTableMap[i] + std::string(";");
338  }
339 
340  shaderStr += std::string("\
341  \nfloat computeGradientOpacity(vec4 grad, int component)\
342  \n {\
343  \n if (component == 0)\
344  \n {\
345  \n return texture1D(in_gradientTransferFunc, grad.w).r;\
346  \n }\
347  \n if (component == 1)\
348  \n {\
349  \n return texture1D(in_gradientTransferFunc1, grad.w).r;\
350  \n }\
351  \n if (component == 2)\
352  \n {\
353  \n return texture1D(in_gradientTransferFunc2, grad.w).r;\
354  \n }\
355  \n if (component == 3)\
356  \n {\
357  \n return texture1D(in_gradientTransferFunc3, grad.w).r;\
358  \n }\
359  \n }"
360  );
361  }
362 
363  if (vol->GetProperty()->GetShade() &&
364  !vol->GetProperty()->HasGradientOpacity())
365  {
366  shaderStr += std::string("\
367  \nvec4 computeGradient()\
368  \n {\
369  \n vec3 g1;\
370  \n vec3 g2;\
371  \n g1.x = texture3D(in_volume, vec3(g_dataPos + g_xvec)).x;\
372  \n g1.y = texture3D(in_volume, vec3(g_dataPos + g_yvec)).x;\
373  \n g1.z = texture3D(in_volume, vec3(g_dataPos + g_zvec)).x;\
374  \n g2.x = texture3D(in_volume, vec3(g_dataPos - g_xvec)).x;\
375  \n g2.y = texture3D(in_volume, vec3(g_dataPos - g_yvec)).x;\
376  \n g2.z = texture3D(in_volume, vec3(g_dataPos - g_zvec)).x;\
377  \n g1 = g1 * in_volume_scale.r + in_volume_bias.r;\
378  \n g2 = g2 * in_volume_scale.r + in_volume_bias.r;\
379  \n return vec4((g1 - g2), -1.0);\
380  \n }"
381  );
382  }
383  else if (vol->GetProperty()->GetShade() &&
385  {
386  shaderStr += std::string("\
387  \nvec4 computeGradient()\
388  \n {\
389  \n vec3 g1;\
390  \n vec4 g2;\
391  \n g1.x = texture3D(in_volume, vec3(g_dataPos + g_xvec)).x;\
392  \n g1.y = texture3D(in_volume, vec3(g_dataPos + g_yvec)).x;\
393  \n g1.z = texture3D(in_volume, vec3(g_dataPos + g_zvec)).x;\
394  \n g2.x = texture3D(in_volume, vec3(g_dataPos - g_xvec)).x;\
395  \n g2.y = texture3D(in_volume, vec3(g_dataPos - g_yvec)).x;\
396  \n g2.z = texture3D(in_volume, vec3(g_dataPos - g_zvec)).x;\
397  \n g1 = g1*in_volume_scale.r + in_volume_bias.r;\
398  \n g2 = g2*in_volume_scale.r + in_volume_bias.r;\
399  \n g1.x = in_scalarsRange[0] + (\
400  \n in_scalarsRange[1] - in_scalarsRange[0]) * g1.x;\
401  \n g1.y = in_scalarsRange[0] + (\
402  \n in_scalarsRange[1] - in_scalarsRange[0]) * g1.y;\
403  \n g1.z = in_scalarsRange[0] + (\
404  \n in_scalarsRange[1] - in_scalarsRange[0]) * g1.z;\
405  \n g2.x = in_scalarsRange[0] + (\
406  \n in_scalarsRange[1] - in_scalarsRange[0]) * g2.x;\
407  \n g2.y = in_scalarsRange[0] + (\
408  \n in_scalarsRange[1] - in_scalarsRange[0]) * g2.y;\
409  \n g2.z = in_scalarsRange[0] + (\
410  \n in_scalarsRange[1] - in_scalarsRange[0]) * g2.z;\
411  \n g2.xyz = g1 - g2.xyz;\
412  \n g2.x /= g_aspect.x;\
413  \n g2.y /= g_aspect.y;\
414  \n g2.z /= g_aspect.z;\
415  \n float grad_mag = sqrt(g2.x * g2.x +\
416  \n g2.y * g2.y +\
417  \n g2.z * g2.z);\
418  \n if (grad_mag > 0.0)\
419  \n {\
420  \n g2.x /= grad_mag;\
421  \n g2.y /= grad_mag;\
422  \n g2.z /= grad_mag;\
423  \n }\
424  \n else\
425  \n {\
426  \n g2.xyz = vec3(0.0, 0.0, 0.0);\
427  \n }\
428  \n grad_mag = grad_mag * 1.0 / (0.25 * (in_scalarsRange[1] -\
429  \n (in_scalarsRange[0])));\
430  \n grad_mag = clamp(grad_mag, 0.0, 1.0);\
431  \n g2.w = grad_mag;\
432  \n return g2;\
433  \n }"
434  );
435  }
436  else
437  {
438  shaderStr += std::string("\
439  \nvec4 computeGradient()\
440  \n {\
441  \n return vec4(0.0);\
442  \n }");
443  }
444 
445  return shaderStr;
446  }
447 
448  //--------------------------------------------------------------------------
450  vtkVolumeMapper* vtkNotUsed(mapper),
451  vtkVolume* vol,
452  int noOfComponents,
453  int independentComponents,
454  int vtkNotUsed(numberOfLights),
455  int lightingComplexity)
456  {
457  vtkVolumeProperty* volProperty = vol->GetProperty();
458  std::string shaderStr = std::string("\
459  \nvec4 computeLighting(vec4 color)\
460  \n {\
461  \n vec4 finalColor = vec4(0.0);"
462  );
463 
464  if (volProperty->GetShade() || volProperty->HasGradientOpacity())
465  {
466  shaderStr += std::string("\
467  \n // Compute gradient function only once\
468  \n vec4 gradient = computeGradient();"
469  );
470  }
471 
472  if (volProperty->GetShade())
473  {
474  if (lightingComplexity == 1)
475  {
476  shaderStr += std::string("\
477  \n vec3 diffuse = vec3(0.0);\
478  \n vec3 specular = vec3(0.0);\
479  \n vec3 normal = gradient.xyz / in_cellSpacing;\
480  \n float normalLength = length(normal);\
481  \n if (normalLength > 0.0)\
482  \n {\
483  \n normal = normalize(normal);\
484  \n }\
485  \n else\
486  \n {\
487  \n normal = vec3(0.0, 0.0, 0.0);\
488  \n }\
489  \n float nDotL = dot(normal, g_ldir);\
490  \n float nDotH = dot(normal, g_h);\
491  \n if (nDotL < 0.0 && in_twoSidedLighting)\
492  \n {\
493  \n nDotL = -nDotL;\
494  \n }\
495  \n if (nDotH < 0.0 && in_twoSidedLighting)\
496  \n {\
497  \n nDotH = -nDotH;\
498  \n }\
499  \n if (nDotL > 0)\
500  \n {\
501  \n diffuse = nDotL * in_diffuse * in_lightDiffuseColor[0]\
502  \n * color.rgb;\
503  \n }\
504  \n specular = pow(nDotH, in_shininess) * in_specular *\
505  \n in_lightSpecularColor[0];\
506  \n // For the headlight, ignore the light's ambient color\
507  \n // for now as it is causing the old mapper tests to fail\
508  \n finalColor.xyz = in_ambient * color.rgb + diffuse + specular;"
509  );
510  }
511  else if (lightingComplexity == 2)
512  {
513  shaderStr += std::string("\
514  \n g_fragWorldPos = in_modelViewMatrix * in_volumeMatrix *\
515  \n in_textureDatasetMatrix * vec4(-g_dataPos, 1.0);\
516  \n if (g_fragWorldPos.w != 0.0)\
517  \n {\
518  \n g_fragWorldPos /= g_fragWorldPos.w;\
519  \n }\
520  \n vec3 vdir = normalize(g_fragWorldPos.xyz);\
521  \n vec3 normal = gradient.xyz;\
522  \n vec3 ambient = vec3(0.0);\
523  \n vec3 diffuse = vec3(0.0);\
524  \n vec3 specular = vec3(0.0);\
525  \n float normalLength = length(normal);\
526  \n if (normalLength > 0.0)\
527  \n {\
528  \n normal = normalize(in_texureToEyeIt * normal);\
529  \n }\
530  \n else\
531  \n {\
532  \n normal = vec3(0.0, 0.0, 0.0);\
533  \n }\
534  \n for (int lightNum = 0; lightNum < in_numberOfLights; lightNum++)\
535  \n {\
536  \n vec3 ldir = in_lightDirection[lightNum].xyz;\
537  \n vec3 h = normalize(ldir + vdir);\
538  \n float nDotH = dot(normal, h);\
539  \n if (nDotH < 0.0 && in_twoSidedLighting)\
540  \n {\
541  \n nDotH = -nDotH;\
542  \n }\
543  \n float nDotL = dot(normal, ldir);\
544  \n if (nDotL < 0.0 && in_twoSidedLighting)\
545  \n {\
546  \n nDotL = -nDotL;\
547  \n }\
548  \n if (nDotL > 0)\
549  \n {\
550  \n diffuse += in_lightDiffuseColor[lightNum] * nDotL;\
551  \n }\
552  \n if (nDotH > 0)\
553  \n {\
554  \n specular = in_lightSpecularColor[lightNum] * pow(nDotH, in_shininess);\
555  \n }\
556  \n ambient += in_lightAmbientColor[lightNum];\
557  \n }\
558  \n finalColor.xyz = in_ambient * ambient +\
559  \n in_diffuse * diffuse * color.rgb +\
560  \n in_specular * specular;"
561  );
562  }
563  else if (lightingComplexity == 3)
564  {
565  shaderStr += std::string("\
566  \n g_fragWorldPos = in_modelViewMatrix * in_volumeMatrix *\
567  \n in_textureDatasetMatrix * vec4(g_dataPos, 1.0);\
568  \n if (g_fragWorldPos.w != 0.0)\
569  \n {\
570  \n g_fragWorldPos /= g_fragWorldPos.w;\
571  \n }\
572  \n vec3 viewDirection = normalize(-g_fragWorldPos.xyz);\
573  \n vec3 ambient = vec3(0,0,0);\
574  \n vec3 diffuse = vec3(0,0,0);\
575  \n vec3 specular = vec3(0,0,0);\
576  \n vec3 vertLightDirection;\
577  \n vec3 normal = normalize(in_texureToEyeIt * gradient.xyz);\
578  \n vec3 lightDir;\
579  \n for (int lightNum = 0; lightNum < in_numberOfLights; lightNum++)\
580  \n {\
581  \n float attenuation = 1.0;\
582  \n // directional\
583  \n lightDir = in_lightDirection[lightNum];\
584  \n if (in_lightPositional[lightNum] == 0)\
585  \n {\
586  \n vertLightDirection = lightDir;\
587  \n }\
588  \n else\
589  \n {\
590  \n vertLightDirection = (g_fragWorldPos.xyz - in_lightPosition[lightNum]);\
591  \n float distance = length(vertLightDirection);\
592  \n vertLightDirection = normalize(vertLightDirection);\
593  \n attenuation = 1.0 /\
594  \n (in_lightAttenuation[lightNum].x\
595  \n + in_lightAttenuation[lightNum].y * distance\
596  \n + in_lightAttenuation[lightNum].z * distance * distance);\
597  \n // per OpenGL standard cone angle is 90 or less for a spot light\
598  \n if (in_lightConeAngle[lightNum] <= 90.0)\
599  \n {\
600  \n float coneDot = dot(vertLightDirection, lightDir);\
601  \n // if inside the cone\
602  \n if (coneDot >= cos(radians(in_lightConeAngle[lightNum])))\
603  \n {\
604  \n attenuation = attenuation * pow(coneDot, in_lightExponent[lightNum]);\
605  \n }\
606  \n else\
607  \n {\
608  \n attenuation = 0.0;\
609  \n }\
610  \n }\
611  \n }\
612  \n // diffuse and specular lighting\
613  \n float nDotL = dot(normal, vertLightDirection);\
614  \n if (nDotL < 0.0 && in_twoSidedLighting)\
615  \n {\
616  \n nDotL = -nDotL;\
617  \n }\
618  \n if (nDotL > 0)\
619  \n {\
620  \n float df = max(0.0, attenuation * nDotL);\
621  \n diffuse += (df * in_lightDiffuseColor[lightNum]);\
622  \n }\
623  \n vec3 h = normalize(vertLightDirection + viewDirection);\
624  \n float nDotH = dot(normal, h);\
625  \n if (nDotH < 0.0 && in_twoSidedLighting)\
626  \n {\
627  \n nDotH = -nDotH;\
628  \n }\
629  \n if (nDotH > 0)\
630  \n {\
631  \n float sf = attenuation * pow(nDotH, in_shininess);\
632  \n specular += (sf * in_lightSpecularColor[lightNum]);\
633  \n }\
634  \n ambient += in_lightAmbientColor[lightNum];\
635  \n }\
636  \n finalColor.xyz = in_ambient * ambient + in_diffuse *\
637  \n diffuse * color.rgb + in_specular * specular;\
638  ");
639  }
640  }
641  else
642  {
643  shaderStr += std::string(
644  "\n finalColor = vec4(color.rgb, 0.0);"
645  );
646  }
647 
648  if (noOfComponents == 1 && volProperty->HasGradientOpacity())
649  {
650  shaderStr += std::string("\
651  \n if (gradient.w >= 0.0)\
652  \n {\
653  \n color.a = color.a *\
654  \n computeGradientOpacity(gradient);\
655  \n }"
656  );
657  }
658  else if (noOfComponents > 1 && independentComponents &&
659  volProperty->HasGradientOpacity())
660  {
661  shaderStr += std::string("\
662  \n if (gradient.w >= 0.0)\
663  \n {\
664  \n for (int i = 0; i < in_noOfComponents; ++i)\
665  \n {\
666  \n color.a = color.a *\
667  \n computeGradientOpacity(gradient, i) * in_componentWeight[i];\
668  \n }"
669  );
670  }
671 
672  shaderStr += std::string("\
673  \n finalColor.a = color.a;\
674  \n return finalColor;\
675  \n }"
676  );
677 
678  return shaderStr;
679  }
680 
681  //--------------------------------------------------------------------------
683  vtkVolumeMapper* vtkNotUsed(mapper),
684  vtkVolume* vtkNotUsed(vol),
685  int vtkNotUsed(noOfComponents))
686  {
687  if (!ren->GetActiveCamera()->GetParallelProjection())
688  {
689  return std::string("\
690  \nvec3 computeRayDirection()\
691  \n {\
692  \n return normalize(ip_vertexPos.xyz - g_eyePosObj.xyz);\
693  \n }");
694  }
695  else
696  {
697  return std::string("\
698  \nuniform vec3 in_projectionDirection;\
699  \nvec3 computeRayDirection()\
700  \n {\
701  \n return normalize((in_inverseVolumeMatrix *\
702  \n vec4(in_projectionDirection, 0.0)).xyz);\
703  \n }");
704  }
705  }
706 
707  //--------------------------------------------------------------------------
709  vtkVolumeMapper* vtkNotUsed(mapper),
710  vtkVolume* vtkNotUsed(vol),
711  int noOfComponents,
712  int independentComponents,
713  std::map<int, std::string> colorTableMap)
714  {
715  if (noOfComponents == 1)
716  {
717  return std::string("\
718  \nuniform sampler1D in_colorTransferFunc;\
719  \nvec4 computeColor(vec4 scalar, float opacity)\
720  \n {\
721  \n return computeLighting(vec4(texture1D(in_colorTransferFunc,\
722  \n scalar.w).xyz, opacity));\
723  \n }");
724  }
725  else if (noOfComponents > 1 && independentComponents)
726  {
727  std::string shaderStr;
728  std::ostringstream toString;
729  for (int i = 0; i < noOfComponents; ++i)
730  {
731  shaderStr += std::string("\n uniform sampler1D ") +
732  colorTableMap[i] + std::string(";");
733  }
734 
735  shaderStr += std::string("\
736  \nvec4 computeColor(vec4 scalar, float opacity, int component)\
737  \n {");
738 
739  for (int i = 0; i < noOfComponents; ++i)
740  {
741  toString << i;
742  shaderStr += std::string("\
743  \n if (component == " + toString.str() + ")");
744 
745  shaderStr += std::string("\
746  \n {\
747  \n return computeLighting(vec4(texture1D(\
748  \n in_colorTransferFunc");
749  shaderStr += (i == 0 ? "" : toString.str());
750  shaderStr += std::string(",\
751  \n scalar[" + toString.str() + "]).xyz,\
752  \n opacity));\
753  \n }");
754 
755  // Reset
756  toString.str("");
757  toString.clear();
758  }
759 
760  shaderStr += std::string("\n }");
761  return shaderStr;
762  }
763  else if (noOfComponents == 2&& !independentComponents)
764  {
765  return std::string("\
766  \nuniform sampler1D in_colorTransferFunc;\
767  \nvec4 computeColor(vec4 scalar, float opacity)\
768  \n {\
769  \n return computeLighting(vec4(texture1D(in_colorTransferFunc,\
770  \n scalar.x).xyz,\
771  \n opacity));\
772  \n }");
773  }
774  else
775  {
776  return std::string("\
777  \nvec4 computeColor(vec4 scalar, float opacity)\
778  \n {\
779  \n return computeLighting(vec4(scalar.xyz, opacity));\
780  \n }");
781  }
782  }
783 
784  //--------------------------------------------------------------------------
786  vtkVolumeMapper* vtkNotUsed(mapper),
787  vtkVolume* vtkNotUsed(vol),
788  int noOfComponents,
789  int independentComponents,
790  std::map<int, std::string> opacityTableMap)
791  {
792  if (noOfComponents > 1 && independentComponents)
793  {
794  std::string shaderStr;
795  std::ostringstream toString;
796 
797  for (int i = 0; i < noOfComponents; ++i)
798  {
799  shaderStr += std::string("\n uniform sampler1D ") +
800  opacityTableMap[i] + std::string(";");
801 
802  }
803 
804  shaderStr += std::string("\
805  \nfloat computeOpacity(vec4 scalar, int component)\
806  \n {");
807 
808  for (int i = 0; i < noOfComponents; ++i)
809  {
810  toString << i;
811  shaderStr += std::string("\
812  \n if (component == " + toString.str() + ")");
813 
814  shaderStr += std::string("\
815  \n {\
816  \n return texture1D(in_opacityTransferFunc");
817  shaderStr += (i == 0 ? "" : toString.str());
818  shaderStr += std::string(",scalar[" + toString.str() + "]).r;\
819  \n }");
820 
821  // Reset
822  toString.str("");
823  toString.clear();
824  }
825 
826  shaderStr += std::string("\n }");
827  return shaderStr;
828  }
829  else if (noOfComponents == 2 && !independentComponents)
830  {
831  return std::string("\
832  \nuniform sampler1D in_opacityTransferFunc;\
833  \nfloat computeOpacity(vec4 scalar)\
834  \n {\
835  \n return texture1D(in_opacityTransferFunc, scalar.y).r;\
836  \n }");
837  }
838  else
839  {
840  return std::string("\
841  \nuniform sampler1D in_opacityTransferFunc;\
842  \nfloat computeOpacity(vec4 scalar)\
843  \n {\
844  \n return texture1D(in_opacityTransferFunc, scalar.w).r;\
845  \n }");
846  }
847  }
848 
849  //--------------------------------------------------------------------------
851  vtkVolumeMapper* vtkNotUsed(mapper),
852  vtkVolume* vtkNotUsed(vol))
853  {
854  return std::string();
855  }
856 
857  //--------------------------------------------------------------------------
859  vtkVolumeMapper* vtkNotUsed(mapper),
860  vtkVolume* vtkNotUsed(vol))
861  {
862  return std::string();
863  }
864 
865  //--------------------------------------------------------------------------
867  vtkVolumeMapper* mapper,
868  vtkVolume* vtkNotUsed(vol))
869  {
871  {
872  return std::string("\
873  \n // We get data between 0.0 - 1.0 range\
874  \n bool l_firstValue = true;\
875  \n vec4 l_maxValue = vec4(0.0);"
876  );
877  }
879  {
880  return std::string("\
881  \n //We get data between 0.0 - 1.0 range\
882  \n bool l_firstValue = true;\
883  \n vec4 l_minValue = vec4(1.0);"
884  );
885  }
886  else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
887  {
888  return std::string("\
889  \n //We get data between 0.0 - 1.0 range\
890  \n float l_sumValue = 0.0;"
891  );
892  }
893  else
894  {
895  return std::string();
896  }
897  }
898 
899  //--------------------------------------------------------------------------
901  vtkVolumeMapper* mapper,
902  vtkVolume* vtkNotUsed(vol),
903  vtkImageData* maskInput,
904  vtkVolumeMask* mask, int maskType,
905  int noOfComponents,
906  int independentComponents = 0)
907  {
908  std::string shaderStr = std::string("\
909  \n if (!l_skip)\
910  \n {\
911  \n vec4 scalar = texture3D(in_volume, g_dataPos);"
912  );
913 
914  // simulate old intensity textures
915  if (noOfComponents == 1)
916  {
917  shaderStr += std::string("\
918  \n scalar.r = scalar.r*in_volume_scale.r + in_volume_bias.r;\
919  \n scalar = vec4(scalar.r,scalar.r,scalar.r,scalar.r);"
920  );
921  }
922  else
923  {
924  // handle bias and scale
925  shaderStr += std::string("\
926  \n scalar = scalar*in_volume_scale + in_volume_bias;"
927  );
928  }
929 
931  {
932  if (noOfComponents > 1)
933  {
934  if (!independentComponents)
935  {
936  shaderStr += std::string("\
937  \n if (l_maxValue.w < scalar.w || l_firstValue)\
938  \n {\
939  \n l_maxValue = scalar;\
940  \n }\
941  \n\
942  \n if (l_firstValue)\
943  \n {\
944  \n l_firstValue = false;\
945  \n }"
946  );
947  }
948  else
949  {
950  shaderStr += std::string("\
951  \n for (int i = 0; i < in_noOfComponents; ++i)\
952  \n {\
953  \n if (l_maxValue[i] < scalar[i] || l_firstValue)\
954  \n {\
955  \n l_maxValue[i] = scalar[i];\
956  \n }\
957  \n }\
958  \n if (l_firstValue)\
959  \n {\
960  \n l_firstValue = false;\
961  \n }"
962  );
963  }
964  }
965  else
966  {
967  shaderStr += std::string("\
968  \n if (l_maxValue.w < scalar.x || l_firstValue)\
969  \n {\
970  \n l_maxValue.w = scalar.x;\
971  \n }\
972  \n\
973  \n if (l_firstValue)\
974  \n {\
975  \n l_firstValue = false;\
976  \n }"
977  );
978  }
979  }
981  {
982  if (noOfComponents > 1)
983  {
984  if (!independentComponents)
985  {
986  shaderStr += std::string("\
987  \n if (l_minValue.w > scalar.w || l_firstValue)\
988  \n {\
989  \n l_minValue = scalar;\
990  \n }\
991  \n\
992  \n if (l_firstValue)\
993  \n {\
994  \n l_firstValue = false;\
995  \n }"
996  );
997  }
998  else
999  {
1000  shaderStr += std::string("\
1001  \n for (int i = 0; i < in_noOfComponents; ++i)\
1002  \n {\
1003  \n if (l_minValue[i] < scalar[i] || l_firstValue)\
1004  \n {\
1005  \n l_minValue[i] = scalar[i];\
1006  \n }\
1007  \n }\
1008  \n if (l_firstValue)\
1009  \n {\
1010  \n l_firstValue = false;\
1011  \n }"
1012  );
1013  }
1014  }
1015  else
1016  {
1017  shaderStr += std::string("\
1018  \n if (l_minValue.w > scalar.x || l_firstValue)\
1019  \n {\
1020  \n l_minValue.w = scalar.x;\
1021  \n }\
1022  \n\
1023  \n if (l_firstValue)\
1024  \n {\
1025  \n l_firstValue = false;\
1026  \n }"
1027  );
1028  }
1029  }
1030  else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
1031  {
1032  if (noOfComponents > 1)
1033  {
1034  if (!independentComponents)
1035  {
1036  shaderStr += std::string("\
1037  \n float opacity = computeOpacity(scalar);\
1038  \n l_sumValue = l_sumValue + opacity * scalar.x;"
1039  );
1040  }
1041  else
1042  {
1043  shaderStr += std::string("\
1044  \n for (int i = 0; i < in_noOfComponents; ++i)\
1045  \n {\
1046  \n float opacity = computeOpacity(scalar, i);\
1047  \n l_sumValue[i] = l_sumValue[i] + opacity * scalar[i];\
1048  \n }"
1049  );
1050  }
1051  }
1052  else
1053  {
1054  shaderStr += std::string("\
1055  \n float opacity = computeOpacity(scalar);\
1056  \n l_sumValue = l_sumValue + opacity * scalar.x;"
1057  );
1058  }
1059  }
1060  else if (mapper->GetBlendMode() == vtkVolumeMapper::COMPOSITE_BLEND)
1061  {
1062  if (noOfComponents > 1 && independentComponents)
1063  {
1064  shaderStr += std::string("\
1065  \n vec4 color[4]; vec4 tmp = vec4(0.0);\
1066  \n float totalAlpha = 0.0;\
1067  \n for (int i = 0; i < in_noOfComponents; ++i)\
1068  \n {\
1069  ");
1070  if (!mask || !maskInput ||
1072  {
1073  shaderStr += std::string("\
1074  \n // Data fetching from the red channel of volume texture\
1075  \n color[i][3] = computeOpacity(scalar, i);\
1076  \n color[i] = computeColor(scalar, color[i][3], i);\
1077  \n totalAlpha += color[i][3] * in_componentWeight[i];\
1078  \n }\
1079  \n if (totalAlpha > 0.0)\
1080  \n {\
1081  \n for (int i = 0; i < in_noOfComponents; ++i)\
1082  \n {\
1083  \n tmp.x += color[i].x * color[i].w * in_componentWeight[i] ;\
1084  \n tmp.y += color[i].y * color[i].w * in_componentWeight[i];\
1085  \n tmp.z += color[i].z * color[i].w * in_componentWeight[i];\
1086  \n tmp.w += ((color[i].w * color[i].w)/totalAlpha);\
1087  \n }\
1088  \n }\
1089  \n g_fragColor = (1.0f - g_fragColor.a) * tmp + g_fragColor;"
1090  );
1091  }
1092  }
1093  else
1094  {
1095  if (!mask || !maskInput ||
1097  {
1098  shaderStr += std::string("\
1099  \n vec4 g_srcColor = vec4(0.0);\
1100  \n g_srcColor.a = computeOpacity(scalar);\
1101  \n if (g_srcColor.a > 0.0)\
1102  \n {\
1103  \n g_srcColor = computeColor(scalar, g_srcColor.a);"
1104  );
1105  }
1106 
1107  shaderStr += std::string("\
1108  \n // Opacity calculation using compositing:\
1109  \n // here we use front to back compositing scheme whereby the current\
1110  \n // sample value is multiplied to the currently accumulated alpha\
1111  \n // and then this product is subtracted from the sample value to\
1112  \n // get the alpha from the previous steps.\
1113  \n // Next, this alpha is multiplied with the current sample colour\
1114  \n // and accumulated to the composited colour. The alpha value from\
1115  \n // the previous steps is then accumulated to the composited colour\
1116  \n // alpha.\
1117  \n g_srcColor.rgb *= g_srcColor.a;\
1118  \n g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;"
1119  );
1120 
1121  if (!mask || !maskInput ||
1123  {
1124  shaderStr += std::string("\
1125  \n }"
1126  );
1127  }
1128  }
1129  }
1130  else
1131  {
1132  shaderStr += std::string();
1133  }
1134 
1135  shaderStr += std::string("\
1136  \n }"
1137  );
1138  return shaderStr;
1139  }
1140 
1141  //--------------------------------------------------------------------------
1143  vtkVolumeMapper* mapper,
1144  vtkVolume* vtkNotUsed(vol),
1145  int noOfComponents,
1146  int independentComponents = 0)
1147  {
1149  {
1150  if (noOfComponents > 1 && independentComponents)
1151  {
1152  return std::string("\
1153  \n vec4 g_srcColor = vec4(0);\
1154  \n for (int i = 0; i < in_noOfComponents; ++i)\
1155  \n {\
1156  \n vec4 tmp = computeColor(l_maxValue, computeOpacity(l_maxValue, i), i);\
1157  \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
1158  \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
1159  \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
1160  \n g_srcColor[3] += tmp[3] * in_componentWeight[i];\
1161  \n }\
1162  \n g_fragColor = g_srcColor;"
1163  );
1164  }
1165  else
1166  {
1167  return std::string("\
1168  \n vec4 g_srcColor = computeColor(l_maxValue,\
1169  computeOpacity(l_maxValue));\
1170  \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
1171  \n g_fragColor.a = g_srcColor.a;"
1172  );
1173  }
1174  }
1176  {
1177  if (noOfComponents > 1 && independentComponents)
1178  {
1179  return std::string("\
1180  \n vec4 g_srcColor = vec4(0);\
1181  \n for (int i = 0; i < in_noOfComponents; ++i)\
1182  \n {\
1183  \n vec4 tmp = computeColor(l_minValue, computeOpacity(l_minValue, i), i);\
1184  \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
1185  \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
1186  \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
1187  \n g_srcColor[2] += tmp[3] * tmp[3] * in_componentWeight[i];\
1188  \n }\
1189  \n g_fragColor = g_srcColor;"
1190  );
1191  }
1192  else
1193  {
1194  return std::string("\
1195  \n vec4 g_srcColor = computeColor(l_minValue,\
1196  \n computeOpacity(l_minValue));\
1197  \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
1198  \n g_fragColor.a = g_srcColor.a;"
1199  );
1200  }
1201  }
1202  else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
1203  {
1204  if (noOfComponents > 1 && independentComponents)
1205  {
1206  return std::string("\
1207  \n l_sumValue = clamp(l_sumValue, 0.0, 1.0);\
1208  \n g_fragColor = vec4(l_sumValue);"
1209  );
1210  }
1211  else
1212  {
1213  return std::string("\
1214  \n l_sumValue = clamp(l_sumValue, 0.0, 1.0);\
1215  \n g_fragColor = vec4(vec3(l_sumValue), 1.0);"
1216  );
1217  }
1218  }
1219  else
1220  {
1221  return std::string();
1222  }
1223  }
1224 
1225  //--------------------------------------------------------------------------
1227  vtkVolumeMapper* vtkNotUsed(mapper),
1228  vtkVolume* vtkNotUsed(vol))
1229  {
1230  return std::string();
1231  }
1232 
1233  //--------------------------------------------------------------------------
1235  vtkVolumeMapper* vtkNotUsed(mapper),
1236  vtkVolume* vtkNotUsed(vol))
1237  {
1238  return std::string();
1239  }
1240 
1241  //--------------------------------------------------------------------------
1243  vtkVolumeMapper* vtkNotUsed(mapper),
1244  vtkVolume* vtkNotUsed(vol))
1245  {
1246  return std::string("\
1247  \n // Minimum texture access coordinate\
1248  \n const vec3 l_tex_min = vec3(0);\
1249  \n\
1250  \n // Maximum texture access coordinate\
1251  \n const vec3 l_tex_max = vec3(1);\
1252  \n\
1253  \n // Flag to indicate if the raymarch loop should terminate \
1254  \n bool stop = false;\
1255  \n\
1256  \n // 2D Texture fragment coordinates [0,1] from fragment coordinates \
1257  \n // the frame buffer texture has the size of the plain buffer but \
1258  \n // we use a fraction of it. The texture coordinates is less than 1 if \
1259  \n // the reduction factor is less than 1. \
1260  \n // Device coordinates are between -1 and 1. We need texture \
1261  \n // coordinates between 0 and 1 the in_depthSampler buffer has the \
1262  \n // original size buffer. \
1263  \n vec2 fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
1264  \n in_inverseWindowSize;\
1265  \n vec4 l_depthValue = texture2D(in_depthSampler, fragTexCoord);\
1266  \n float l_terminatePointMax = 0.0;\
1267  \n\
1268  \n // Depth test\
1269  \n if(gl_FragCoord.z >= l_depthValue.x)\
1270  \n {\
1271  \n discard;\
1272  \n }\
1273  \n\
1274  \n // color buffer or max scalar buffer have a reduced size.\
1275  \n fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
1276  \n in_inverseOriginalWindowSize;\
1277  \n\
1278  \n // Compute max number of iterations it will take before we hit\
1279  \n // the termination point\
1280  \n\
1281  \n // Abscissa of the point on the depth buffer along the ray.\
1282  \n // point in texture coordinates\
1283  \n vec4 terminatePoint;\
1284  \n terminatePoint.x = (gl_FragCoord.x - in_windowLowerLeftCorner.x) * 2.0 *\
1285  \n in_inverseWindowSize.x - 1.0;\
1286  \n terminatePoint.y = (gl_FragCoord.y - in_windowLowerLeftCorner.y) * 2.0 *\
1287  \n in_inverseWindowSize.y - 1.0;\
1288  \n terminatePoint.z = (2.0 * l_depthValue.x - (gl_DepthRange.near +\
1289  \n gl_DepthRange.far)) / gl_DepthRange.diff;\
1290  \n terminatePoint.w = 1.0;\
1291  \n\
1292  \n // From normalized device coordinates to eye coordinates.\
1293  \n // in_projectionMatrix is inversed because of way VT\
1294  \n // From eye coordinates to texture coordinates\
1295  \n terminatePoint = in_inverseTextureDatasetMatrix *\
1296  \n in_inverseVolumeMatrix *\
1297  \n in_inverseModelViewMatrix *\
1298  \n in_inverseProjectionMatrix *\
1299  \n terminatePoint;\
1300  \n terminatePoint /= terminatePoint.w;\
1301  \n\
1302  \n l_terminatePointMax = length(terminatePoint.xyz - g_dataPos.xyz) /\
1303  \n length(g_dirStep);\
1304  \n float l_currentT = 0.0;");
1305  }
1306 
1307  //--------------------------------------------------------------------------
1309  vtkVolumeMapper* vtkNotUsed(mapper),
1310  vtkVolume* vtkNotUsed(vol))
1311  {
1312  return std::string("\
1313  \n // The two constants l_tex_min and l_tex_max have a value of\
1314  \n // vec3(-1,-1,-1) and vec3(1,1,1) respectively. To determine if the\
1315  \n // data value is outside the in_volume data, we use the sign function.\
1316  \n // The sign function return -1 if the value is less than 0, 0 if the\
1317  \n // value is equal to 0 and 1 if value is greater than 0. Hence, the\
1318  \n // sign function for the calculation (sign(g_dataPos-l_tex_min) and\
1319  \n // sign (l_tex_max-g_dataPos)) will give us vec3(1,1,1) at the\
1320  \n // possible minimum and maximum position.\
1321  \n // When we do a dot product between two vec3(1,1,1) we get answer 3.\
1322  \n // So to be within the dataset limits, the dot product will return a\
1323  \n // value less than 3. If it is greater than 3, we are already out of\
1324  \n // the in_volume dataset\
1325  \n stop = dot(sign(g_dataPos - l_tex_min), sign(l_tex_max - g_dataPos))\
1326  \n < 3.0;\
1327  \n\
1328  \n // If the stopping condition is true we brek out of the ray marching\
1329  \n // loop\
1330  \n if (stop)\
1331  \n {\
1332  \n break;\
1333  \n }\
1334  \n // Early ray termination\
1335  \n // if the currently composited colour alpha is already fully saturated\
1336  \n // we terminated the loop or if we have hit an obstacle in the\
1337  \n // direction of they ray (using depth buffer) we terminate as well.\
1338  \n if((g_fragColor.a > (1 - 1/255.0)) || \
1339  \n l_currentT >= l_terminatePointMax)\
1340  \n {\
1341  \n break;\
1342  \n }\
1343  \n ++l_currentT;"
1344  );
1345  }
1346 
1347  //--------------------------------------------------------------------------
1349  vtkVolumeMapper* vtkNotUsed(mapper),
1350  vtkVolume* vtkNotUsed(vol))
1351  {
1352  return std::string();
1353  }
1354 
1355  //--------------------------------------------------------------------------
1357  vtkVolumeMapper* vtkNotUsed(mapper),
1358  vtkVolume* vtkNotUsed(vol))
1359  {
1360  return std::string();
1361  }
1362 
1363  //--------------------------------------------------------------------------
1365  vtkVolumeMapper* mapper,
1366  vtkVolume* vtkNotUsed(vol))
1367  {
1368  if (!mapper->GetCropping()) {
1369  return std::string();
1370  }
1371 
1372  return std::string("\
1373  \nuniform float cropping_planes[6];\
1374  \nuniform int cropping_flags [32];\
1375  \n// X: axis = 0, Y: axis = 1, Z: axis = 2\
1376  \n// cp Cropping plane bounds (minX, maxX, minY, maxY, minZ, maxZ)\
1377  \nint computeRegionCoord(float cp[6], vec3 pos, int axis)\
1378  \n {\
1379  \n int cpmin = axis * 2;\
1380  \n int cpmax = cpmin + 1;\
1381  \n\
1382  \n if (pos[axis] < cp[cpmin])\
1383  \n {\
1384  \n return 1;\
1385  \n }\
1386  \n else if (pos[axis] >= cp[cpmin] &&\
1387  \n pos[axis] < cp[cpmax])\
1388  \n {\
1389  \n return 2;\
1390  \n }\
1391  \n else if (pos[axis] >= cp[cpmax])\
1392  \n {\
1393  \n return 3;\
1394  \n }\
1395  \n return 0;\
1396  \n }\
1397  \n\
1398  \nint computeRegion(float cp[6], vec3 pos)\
1399  \n {\
1400  \n return (computeRegionCoord(cp, pos, 0) +\
1401  \n (computeRegionCoord(cp, pos, 1) - 1) * 3 +\
1402  \n (computeRegionCoord(cp, pos, 2) - 1) * 9);\
1403  \n }"
1404  );
1405  }
1406 
1407  //--------------------------------------------------------------------------
1409  vtkVolumeMapper* mapper,
1410  vtkVolume* vtkNotUsed(vol))
1411  {
1412  if (!mapper->GetCropping()) {
1413  return std::string();
1414  }
1415 
1416  return std::string("\
1417  \n // Convert cropping region to texture space\
1418  \n float cropping_planes_ts[6];\
1419  \n mat4 datasetToTextureMat = in_inverseTextureDatasetMatrix;\
1420  \n\
1421  \n vec4 temp = vec4(cropping_planes[0], 0.0, 0.0, 1.0);\
1422  \n temp = datasetToTextureMat * temp;\
1423  \n if (temp[3] != 0.0)\
1424  \n {\
1425  \n temp[0] /= temp[3];\
1426  \n }\
1427  \n cropping_planes_ts[0] = temp[0];\
1428  \n\
1429  \n temp = vec4(cropping_planes[1], 0.0, 0.0, 1.0);\
1430  \n temp = datasetToTextureMat * temp;\
1431  \n if (temp[3] != 0.0)\
1432  \n {\
1433  \n temp[0] /= temp[3];\
1434  \n }\
1435  \n cropping_planes_ts[1] = temp[0];\
1436  \n\
1437  \n temp = vec4(0.0, cropping_planes[2], 0.0, 1.0);\
1438  \n temp = datasetToTextureMat * temp;\
1439  \n if (temp[3] != 0.0)\
1440  \n {\
1441  \n temp[1] /= temp[3];\
1442  \n }\
1443  \n cropping_planes_ts[2] = temp[1];\
1444  \n\
1445  \n temp = vec4(0.0, cropping_planes[3], 0.0, 1.0);\
1446  \n temp = datasetToTextureMat * temp;\
1447  \n if (temp[3] != 0.0)\
1448  \n {\
1449  \n temp[1] /= temp[3];\
1450  \n }\
1451  \n cropping_planes_ts[3] = temp[1];\
1452  \n\
1453  \n temp = vec4(0.0, 0.0, cropping_planes[4], 1.0);\
1454  \n temp = datasetToTextureMat * temp;\
1455  \n if (temp[3] != 0.0)\
1456  \n {\
1457  \n temp[2] /= temp[3];\
1458  \n }\
1459  \n cropping_planes_ts[4] = temp[2];\
1460  \n\
1461  \n temp = vec4(0.0, 0.0, cropping_planes[5], 1.0);\
1462  \n temp = datasetToTextureMat * temp;\
1463  \n if (temp[3] != 0.0)\
1464  \n {\
1465  \n temp[2] /= temp[3];\
1466  \n }\
1467  \n cropping_planes_ts[5] = temp[2];"
1468  );
1469  }
1470 
1471  //--------------------------------------------------------------------------
1473  vtkVolumeMapper* mapper,
1474  vtkVolume* vtkNotUsed(vol))
1475  {
1476  if (!mapper->GetCropping()) {
1477  return std::string();
1478  }
1479 
1480  return std::string("\
1481  \n // Determine region\
1482  \n int regionNo = computeRegion(cropping_planes_ts, g_dataPos);\
1483  \n\
1484  \n // Do & operation with cropping flags\
1485  \n // Pass the flag that its Ok to sample or not to sample\
1486  \n if (cropping_flags[regionNo] == 0)\
1487  \n {\
1488  \n // Skip this voxel\
1489  \n l_skip = true;\
1490  \n }"
1491  );
1492  }
1493 
1494  //--------------------------------------------------------------------------
1496  vtkVolumeMapper* vtkNotUsed(mapper),
1497  vtkVolume* vtkNotUsed(vol))
1498  {
1499  return std::string();
1500  }
1501 
1502  //--------------------------------------------------------------------------
1504  vtkVolumeMapper* vtkNotUsed(mapper),
1505  vtkVolume* vtkNotUsed(vol))
1506  {
1507  return std::string();
1508  }
1509 
1510  //--------------------------------------------------------------------------
1512  vtkVolumeMapper* vtkNotUsed(mapper),
1513  vtkVolume* vtkNotUsed(vol))
1514  {
1515  return std::string();
1516  }
1517 
1518  //--------------------------------------------------------------------------
1520  vtkVolumeMapper* mapper,
1521  vtkVolume* vtkNotUsed(vol))
1522  {
1523  if (!mapper->GetClippingPlanes())
1524  {
1525  return std::string();
1526  }
1527  else
1528  {
1529  return std::string("\
1530  \nfloat clippingPlanesTexture[48];\
1531  \nint clippingPlanesSize = int(in_clippingPlanes[0]);\
1532  \n\
1533  \nmat4 world_to_texture_mat = in_inverseTextureDatasetMatrix *\
1534  \n in_inverseVolumeMatrix;\
1535  \nfor (int i = 0; i < clippingPlanesSize; i = i + 6)\
1536  \n {\
1537  \n vec4 origin = vec4(in_clippingPlanes[i + 1],\
1538  \n in_clippingPlanes[i + 2],\
1539  \n in_clippingPlanes[i + 3], 1.0);\
1540  \n vec4 normal = vec4(in_clippingPlanes[i + 4],\
1541  \n in_clippingPlanes[i + 5],\
1542  \n in_clippingPlanes[i + 6], 0.0);\
1543  \n\
1544  \n origin = world_to_texture_mat * origin;\
1545  \n normal = world_to_texture_mat * normal;\
1546  \n\
1547  \n if (origin[3] != 0.0)\
1548  \n {\
1549  \n origin[0] = origin[0] / origin[3];\
1550  \n origin[1] = origin[1] / origin[3];\
1551  \n origin[2] = origin[2] / origin[3];\
1552  \n }\
1553  \n if (normal[3] != 0.0)\
1554  \n {\
1555  \n normal[0] = normal[0] / normal[3];\
1556  \n normal[1] = normal[1] / normal[3];\
1557  \n normal[2] = normal[2] / normal[3];\
1558  \n }\
1559  \n\
1560  \n clippingPlanesTexture[i] = origin[0];\
1561  \n clippingPlanesTexture[i + 1] = origin[1];\
1562  \n clippingPlanesTexture[i + 2] = origin[2];\
1563  \n\
1564  \n clippingPlanesTexture[i + 3] = normal[0];\
1565  \n clippingPlanesTexture[i + 4] = normal[1];\
1566  \n clippingPlanesTexture[i + 5] = normal[2];\
1567  \n }"
1568  );
1569  }
1570  }
1571 
1572  //--------------------------------------------------------------------------
1574  vtkVolumeMapper* mapper,
1575  vtkVolume* vtkNotUsed(vol))
1576  {
1577  if (!mapper->GetClippingPlanes())
1578  {
1579  return std::string();
1580  }
1581  else
1582  {
1583  return std::string("\
1584  \n for (int i = 0; i < (clippingPlanesSize) && !l_skip; i = i + 6)\
1585  \n {\
1586  \n if (dot(vec3(g_dataPos - vec3(clippingPlanesTexture[i],\
1587  \n clippingPlanesTexture[i + 1],\
1588  \n clippingPlanesTexture[i + 2])),\
1589  \n vec3(clippingPlanesTexture[i + 3],\
1590  \n clippingPlanesTexture[i + 4],\
1591  \n clippingPlanesTexture[i + 5])) < 0)\
1592  \n {\
1593  \n l_skip = true;\
1594  \n break;\
1595  \n }\
1596  \n }"
1597  );
1598  }
1599  }
1600 
1601  //--------------------------------------------------------------------------
1603  vtkVolumeMapper* vtkNotUsed(mapper),
1604  vtkVolume* vtkNotUsed(vol))
1605  {
1606  return std::string();
1607  }
1608 
1609  //--------------------------------------------------------------------------
1611  vtkVolumeMapper* vtkNotUsed(mapper),
1612  vtkVolume* vtkNotUsed(vol),
1613  vtkImageData* maskInput,
1614  vtkVolumeMask* mask,
1615  int vtkNotUsed(maskType))
1616  {
1617  if (!mask || !maskInput)
1618  {
1619  return std::string();
1620  }
1621  else
1622  {
1623  return std::string("uniform sampler3D in_mask;");
1624  }
1625  }
1626 
1627  //--------------------------------------------------------------------------
1629  vtkVolumeMapper* vtkNotUsed(mapper),
1630  vtkVolume* vtkNotUsed(vol),
1631  vtkImageData* maskInput,
1632  vtkVolumeMask* mask,
1633  int maskType)
1634  {
1635  if (!mask || !maskInput ||
1637  {
1638  return std::string();
1639  }
1640  else
1641  {
1642  return std::string("\
1643  \nvec4 maskValue = texture3D(in_mask, g_dataPos);\
1644  \nif(maskValue.r <= 0.0)\
1645  \n {\
1646  \n l_skip = true;\
1647  \n }"
1648  );
1649  }
1650  }
1651 
1652  //--------------------------------------------------------------------------
1654  vtkVolumeMapper* vtkNotUsed(mapper),
1655  vtkVolume* vtkNotUsed(vol),
1656  vtkImageData* maskInput,
1657  vtkVolumeMask* mask,
1658  int maskType)
1659  {
1660  if (!mask || !maskInput ||
1662  {
1663  return std::string();
1664  }
1665  else
1666  {
1667  return std::string("\
1668  \nuniform float in_maskBlendFactor;\
1669  \nuniform sampler1D in_mask1;\
1670  \nuniform sampler1D in_mask2;"
1671  );
1672  }
1673  }
1674 
1675  //--------------------------------------------------------------------------
1677  vtkVolumeMapper* vtkNotUsed(mapper),
1678  vtkVolume* vtkNotUsed(vol),
1679  vtkImageData* maskInput,
1680  vtkVolumeMask* mask,
1681  int maskType,
1682  int noOfComponents)
1683  {
1684  if (!mask || !maskInput ||
1686  {
1687  return std::string();
1688  }
1689  else
1690  {
1691  std::string shaderStr = std::string("\
1692  \nvec4 scalar = texture3D(in_volume, g_dataPos);");
1693 
1694  // simulate old intensity textures
1695  if (noOfComponents == 1)
1696  {
1697  shaderStr += std::string("\
1698  \n scalar.r = scalar.r*in_volume_scale.r + in_volume_bias.r;\
1699  \n scalar = vec4(scalar.r,scalar.r,scalar.r,scalar.r);"
1700  );
1701  }
1702  else
1703  {
1704  // handle bias and scale
1705  shaderStr += std::string("\
1706  \n scalar = scalar*in_volume_scale + in_volume_bias;"
1707  );
1708  }
1709 
1710  return shaderStr + std::string("\
1711  \nif (in_maskBlendFactor == 0.0)\
1712  \n {\
1713  \n g_srcColor = computeColor(scalar, computeOpacity(scalar));\
1714  \n }\
1715  \nelse\
1716  \n {\
1717  \n float opacity = computeOpacity(scalar);\
1718  \n // Get the mask value at this same location\
1719  \n vec4 maskValue = texture3D(in_mask, g_dataPos);\
1720  \n if(maskValue.r == 0.0)\
1721  \n {\
1722  \n g_srcColor = computeColor(scalar, opacity);\
1723  \n }\
1724  \n else\
1725  \n {\
1726  \n if (maskValue.r == 1.0/255.0)\
1727  \n {\
1728  \n g_srcColor = texture1D(in_mask1, scalar.w);\
1729  \n }\
1730  \n else\
1731  \n {\
1732  \n // maskValue.r == 2.0/255.0\
1733  \n g_srcColor = texture1D(in_mask2, scalar.w);\
1734  \n }\
1735  \n g_srcColor.a = 1.0;\
1736  \n if(in_maskBlendFactor < 1.0)\
1737  \n {\
1738  \n g_srcColor = (1.0 - in_maskBlendFactor) * computeColor(scalar, opacity)\
1739  \n + in_maskBlendFactor * g_srcColor;\
1740  \n }\
1741  \n }\
1742  \n g_srcColor.a = opacity;\
1743  \n }"
1744  );
1745  }
1746  }
1747 }
1748 
1749 #endif // _vtkVolumeShaderComposer_h
1750 // VTK-HeaderTest-Exclude: vtkVolumeShaderComposer.h
std::string ShadingExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents=0)
std::string BaseImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
represents a volume (data & properties) in a rendered scene
Definition: vtkVolume.h:49
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 GetBlendMode()
std::string BaseInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vol, int lightingComplexity)
abstract specification for renderers
Definition: vtkRenderer.h:63
std::string CroppingDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string ShadingDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(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 ComputeLightingDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vol, int noOfComponents, int independentComponents, int vtkNotUsed(numberOfLights), int lightingComplexity)
virtual vtkPlaneCollection * GetClippingPlanes()
vtkCamera * GetActiveCamera()
int GetShade(int index)
std::string ClippingImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
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:44
bool HasGradientOpacity(int index=0)
std::string ShadingImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeMask *mask, int maskType, int noOfComponents, int independentComponents=0)
virtual int GetParallelProjection()
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 BaseDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int vtkNotUsed(numberOfLights), int lightingComplexity, int noOfComponents, int independentComponents)
std::string ShadingInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
represents the common properties for rendering a volume.
std::string CroppingExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(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))
std::string ClippingInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *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 CroppingInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
vtkVolumeProperty * GetProperty()
virtual int GetCropping()
std::string replace(std::string source, const std::string &search, const std::string replace, bool all)
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 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)