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 <string>
28 
29 namespace vtkvolume
30 {
31  //--------------------------------------------------------------------------
33  const std::string replace, bool all)
34  {
35  std::string::size_type pos = 0;
36  bool first = true;
37  while ((pos = source.find(search, 0)) != std::string::npos)
38  {
39  source.replace(pos, search.length(), replace);
40  pos += search.length();
41  if (first)
42  {
43  first = false;
44  if (!all)
45  {
46  return source;
47  }
48  }
49  }
50  return source;
51  }
52 
53  //--------------------------------------------------------------------------
55  vtkVolumeMapper* vtkNotUsed(mapper),
56  vtkVolume* vtkNotUsed(vol))
57  {
58  return std::string(
59  "mat4 ogl_projection_matrix = m_projection_matrix; \n\
60  mat4 ogl_modelview_matrix = m_modelview_matrix; \n\
61  vec4 pos = ogl_projection_matrix * ogl_modelview_matrix * \n\
62  m_volume_matrix * vec4(m_in_vertex_pos.xyz, 1); \n\
63  gl_Position = pos;"
64  );
65  }
66 
67  //--------------------------------------------------------------------------
69  vtkVolumeMapper* vtkNotUsed(mapper),
70  vtkVolume* vtkNotUsed(vol))
71  {
72  return std::string(
73  "// Assuming point data only. Also, we offset the texture coordinate \n\
74  // to account for OpenGL treating voxel at the center of the cell. \n\
75  vec3 uvx = (m_in_vertex_pos - m_vol_extents_min) / \n\
76  (m_vol_extents_max - m_vol_extents_min); \n\
77  vec3 delta = m_texture_extents_max - m_texture_extents_min; \n\
78  m_texture_coords = (uvx * (delta - vec3(1.0)) + vec3(0.5)) / delta;"
79  );
80  }
81 
82  //--------------------------------------------------------------------------
84  vtkVolumeMapper* vtkNotUsed(mapper),
85  vtkVolume* vtkNotUsed(vol))
86  { return std::string(
87  "uniform mat4 m_modelview_matrix; \n\
88  uniform mat4 m_projection_matrix; \n\
89  uniform mat4 m_volume_matrix; \n\
90  \n\
91  uniform vec3 m_vol_extents_min; \n\
92  uniform vec3 m_vol_extents_max; \n\
93  \n\
94  uniform vec3 m_texture_extents_max; \n\
95  uniform vec3 m_texture_extents_min;"
96  );
97  }
98 
99  //--------------------------------------------------------------------------
101  vtkVolumeMapper* vtkNotUsed(mapper),
102  vtkVolume* vtkNotUsed(vol))
103  {
104  return std::string(
105  "// Volume dataset \n\
106  uniform sampler3D m_volume; \n\
107  \n\
108  uniform sampler2D m_noise_sampler; \n\
109  uniform sampler2D m_depth_sampler; \n\
110  \n\
111  // Camera position \n\
112  uniform vec3 m_camera_pos; \n\
113  uniform vec3 m_light_pos; \n\
114  \n\
115  // view and model matrices \n\
116  uniform mat4 m_volume_matrix; \n\
117  uniform mat4 m_inverse_volume_matrix; \n\
118  uniform mat4 m_projection_matrix; \n\
119  uniform mat4 m_inverse_projection_matrix; \n\
120  uniform mat4 m_modelview_matrix; \n\
121  uniform mat4 m_inverse_modelview_matrix; \n\
122  uniform mat4 m_texture_dataset_matrix; \n\
123  uniform mat4 m_inverse_texture_dataset_matrix; \n\
124  \n\
125  // Ray step size \n\
126  uniform vec3 m_cell_step; \n\
127  uniform vec2 m_scalars_range; \n\
128  uniform vec3 m_cell_spacing; \n\
129  \n\
130  // Sample distance \n\
131  uniform float m_sample_distance; \n\
132  \n\
133  // Scales \n\
134  uniform vec3 m_cell_scale; \n\
135  uniform vec2 m_window_lower_left_corner; \n\
136  uniform vec2 m_inv_original_window_size; \n\
137  uniform vec2 m_inv_window_size; \n\
138  uniform vec3 m_texture_extents_max; \n\
139  uniform vec3 m_texture_extents_min; \n\
140  \n\
141  // Material and lighting \n\
142  uniform vec3 m_diffuse; \n\
143  uniform vec3 m_ambient; \n\
144  uniform vec3 m_specular; \n\
145  uniform float m_shininess; \n\
146  // Other useful variales; \n\
147  vec4 g_src_color; \n\
148  vec4 g_light_pos_obj; \n\
149  vec4 g_eye_pos_obj; ");
150  }
151 
152  //--------------------------------------------------------------------------
154  vtkVolumeMapper* vtkNotUsed(mapper),
155  vtkVolume* vtkNotUsed(vol))
156  {
157  return std::string(
158  "g_light_pos_obj; \n\
159  \n\
160  // Get the 3D texture coordinates for lookup into the m_volume dataset \n\
161  g_data_pos = m_texture_coords.xyz; \n\
162  \n\
163  // Eye position in object space \n\
164  g_eye_pos_obj = (m_inverse_volume_matrix * vec4(m_camera_pos, 1.0)); \n\
165  if (g_eye_pos_obj.w != 0.0) \n\
166  { \n\
167  g_eye_pos_obj.x /= g_eye_pos_obj.w; \n\
168  g_eye_pos_obj.y /= g_eye_pos_obj.w; \n\
169  g_eye_pos_obj.z /= g_eye_pos_obj.w; \n\
170  g_eye_pos_obj.w = 1.0; \n\
171  } \n\
172  \n\
173  // Getting the ray marching direction (in object space); \n\
174  vec3 geom_dir = computeRayDirection(); \n\
175  \n\
176  // Multiply the raymarching direction with the step size to get the \n\
177  // sub-step size we need to take at each raymarching step \n\
178  g_dir_step = (m_inverse_texture_dataset_matrix * \n\
179  vec4(geom_dir, 0.0)).xyz * m_sample_distance; \n\
180  \n\
181  g_data_pos += g_dir_step * texture2D(m_noise_sampler, g_data_pos.xy).x;\n\
182  \n\
183  // Flag to deternmine if voxel should be considered for the rendering \n\
184  bool l_skip = false;");
185  }
186 
187  //--------------------------------------------------------------------------
189  vtkVolumeMapper* vtkNotUsed(mapper),
190  vtkVolume* vtkNotUsed(vol))
191  {
192  return std::string("\n\
193  l_skip = false;");
194  }
195 
196  //--------------------------------------------------------------------------
198  vtkVolumeMapper* vtkNotUsed(mapper),
199  vtkVolume* vtkNotUsed(vol))
200  {
201  return std::string("");
202  }
203 
204  //--------------------------------------------------------------------------
206  vtkVolumeMapper* vtkNotUsed(mapper),
207  vtkVolume* vol,
208  int vtkNotUsed(numberOfComponents))
209  {
210  if (vol->GetProperty()->GetShade() &&
212  {
213  return std::string(" \n\
214  vec3 computeGradient() \n\
215  { \n\
216  vec3 g1; \n\
217  vec3 g2; \n\
218  vec3 xvec = vec3(m_cell_step[0], 0.0, 0.0); \n\
219  vec3 yvec = vec3(0.0, m_cell_step[1], 0.0); \n\
220  vec3 zvec = vec3(0.0, 0.0, m_cell_step[2]); \n\
221  g1.x = texture3D(m_volume, vec3(g_data_pos + xvec)).x; \n\
222  g1.y = texture3D(m_volume, vec3(g_data_pos + yvec)).x; \n\
223  g1.z = texture3D(m_volume, vec3(g_data_pos + zvec)).x; \n\
224  g2.x = texture3D(m_volume, vec3(g_data_pos - xvec)).x; \n\
225  g2.y = texture3D(m_volume, vec3(g_data_pos - yvec)).x; \n\
226  g2.z = texture3D(m_volume, vec3(g_data_pos - zvec)).x; \n\
227  return (g1 - g2); \n\
228  }");
229  }
230  else if (vol->GetProperty()->GetShade() &&
232  {
233  return std::string(" \n\
234  vec3 computeGradient() \n\
235  { \n\
236  vec3 g1; \n\
237  vec3 g2; \n\
238  vec3 xvec = vec3(m_cell_step[0], 0.0, 0.0); \n\
239  vec3 yvec = vec3(0.0, m_cell_step[1], 0.0); \n\
240  vec3 zvec = vec3(0.0, 0.0, m_cell_step[2]); \n\
241  g1.x = texture3D(m_volume, vec3(g_data_pos + xvec)).x; \n\
242  g1.y = texture3D(m_volume, vec3(g_data_pos + yvec)).x; \n\
243  g1.z = texture3D(m_volume, vec3(g_data_pos + zvec)).x; \n\
244  g2.x = texture3D(m_volume, vec3(g_data_pos - xvec)).x; \n\
245  g2.y = texture3D(m_volume, vec3(g_data_pos - yvec)).x; \n\
246  g2.z = texture3D(m_volume, vec3(g_data_pos - zvec)).x; \n\
247  g1.x = m_scalars_range[0] + ( \n\
248  m_scalars_range[1] - m_scalars_range[0]) * g1.x; \n\
249  g1.y = m_scalars_range[0] + ( \n\
250  m_scalars_range[1] - m_scalars_range[0]) * g1.y; \n\
251  g1.z = m_scalars_range[0] + ( \n\
252  m_scalars_range[1] - m_scalars_range[0]) * g1.z; \n\
253  g2.x = m_scalars_range[0] + ( \n\
254  m_scalars_range[1] - m_scalars_range[0]) * g2.x; \n\
255  g2.y = m_scalars_range[0] + ( \n\
256  m_scalars_range[1] - m_scalars_range[0]) * g2.y; \n\
257  g2.z = m_scalars_range[0] + ( \n\
258  m_scalars_range[1] - m_scalars_range[0]) * g2.z; \n\
259  g2 = g1 - g2; \n\
260  return g2; \n\
261  }");
262  }
263  else
264  {
265  return std::string(
266  "vec3 computeGradient() \n\
267  { \n\
268  return vec3(0.0); \n\
269  }");
270  }
271  }
272 
273  //--------------------------------------------------------------------------
275  vtkVolumeMapper* vtkNotUsed(mapper),
276  vtkVolume* vol,
277  int vtkNotUsed(numberOfComponents))
278  {
279  vtkVolumeProperty* volProperty = vol->GetProperty();
280  if (volProperty->GetShade() &&
281  volProperty->GetDisableGradientOpacity())
282  {
283  return std::string(" \n\
284  vec4 computeLighting(vec4 color) \n\
285  {\n\
286  vec3 ldir = normalize(g_light_pos_obj.xyz - m_vertex_pos); \n\
287  vec3 vdir = normalize(g_eye_pos_obj.xyz - m_vertex_pos); \n\
288  vec3 h = normalize(ldir + vdir); \n\
289  vec3 g2 = computeGradient(); \n\
290  g2 = (1.0/m_cell_spacing) * g2; \n\
291  float normalLength = length(g2);\n\
292  if (normalLength > 0.0) \n\
293  { \n\
294  g2 = normalize(g2); \n\
295  } \n\
296  else \n\
297  { \n\
298  g2 = vec3(0.0, 0.0, 0.0); \n\
299  } \n\
300  vec3 final_color = vec3(0.0); \n\
301  float n_dot_l = dot(g2, ldir); \n\
302  float n_dot_h = dot(g2, h); \n\
303  if (n_dot_l < 0.0) \n\
304  { \n\
305  n_dot_l = -n_dot_l; \n\
306  } \n\
307  if (n_dot_h < 0.0) \n\
308  { \n\
309  n_dot_h = -n_dot_h; \n\
310  } \n\
311  final_color += m_ambient * color.rgb; \n\
312  if (n_dot_l > 0) { \n\
313  final_color += m_diffuse * n_dot_l * color.rgb; \n\
314  } \n\
315  final_color += m_specular * pow(n_dot_h, m_shininess); \n\
316  final_color = clamp(final_color, vec3(0.0), vec3(1.0)); \n\
317  return vec4(final_color, color.a); \n\
318  }");
319  }
320  else if (volProperty->GetShade() &&
321  !volProperty->GetDisableGradientOpacity())
322  {
323  return std::string(" \n\
324  uniform sampler1D m_gradient_transfer_func; \n\
325  vec4 computeLighting(vec4 color) \n\
326  { \n\
327  vec3 grad = computeGradient(); \n\
328  vec3 m_spacing = vec3(m_cell_spacing[0], \n\
329  m_cell_spacing[1], \n\
330  m_cell_spacing[2]); \n\
331  vec3 aspect; \n\
332  float avg_spacing = (m_spacing[0] + \n\
333  m_spacing[1] + \n\
334  m_spacing[2])/3.0; \n\
335  // Adjust the aspect \n\
336  aspect.x = m_spacing[0] * 2.0 / avg_spacing; \n\
337  aspect.y = m_spacing[1] * 2.0 / avg_spacing; \n\
338  aspect.z = m_spacing[2] * 2.0 / avg_spacing; \n\
339  grad.x /= aspect.x; \n\
340  grad.y /= aspect.y; \n\
341  grad.z /= aspect.z; \n\
342  float grad_mag = sqrt(grad.x * grad.x + \n\
343  grad.y * grad.y + \n\
344  grad.z * grad.z); \n\
345  if (grad_mag > 0.0) \n\
346  { \n\
347  grad.x /= grad_mag; \n\
348  grad.y /= grad_mag; \n\
349  grad.z /= grad_mag; \n\
350  } \n\
351  else \n\
352  { \n\
353  grad = vec3(0.0, 0.0, 0.0); \n\
354  } \n\
355  grad_mag = grad_mag * 1.0 / (0.25 * (m_scalars_range[1] - \n\
356  (m_scalars_range[0]))); \n\
357  grad_mag = clamp(grad_mag, 0.0, 1.0); \n\
358  vec4 final_color = vec4(0.0); \n\
359  vec3 ldir = normalize(g_light_pos_obj.xyz - m_vertex_pos); \n\
360  vec3 vdir = normalize(g_eye_pos_obj.xyz - m_vertex_pos); \n\
361  vec3 h = normalize(ldir + vdir); \n\
362  float n_dot_l = dot(grad, ldir); \n\
363  float n_dot_h = dot(grad, h); \n\
364  if (n_dot_l < 0.0) \n\
365  { \n\
366  n_dot_l = -n_dot_l; \n\
367  } \n\
368  if (n_dot_h < 0.0) \n\
369  { \n\
370  n_dot_h = -n_dot_h; \n\
371  } \n\
372  final_color.rgb += m_ambient; \n\
373  final_color.rgb += m_diffuse * n_dot_l * color.rgb; \n\
374  final_color.rgb += m_specular * pow(n_dot_h, m_shininess); \n\
375  final_color.rgb = clamp(final_color.rgb, vec3(0.0), vec3(1.0)); \n\
376  final_color.a = color.a * \n\
377  texture1D(m_gradient_transfer_func, grad_mag).w; \n\
378  return final_color; \n\
379  }");
380  }
381  else
382  {
383  return std::string(
384  "vec4 computeLighting(vec4 color) \n\
385  { \n\
386  return color; \n\
387  }");
388  }
389  }
390 
391  //--------------------------------------------------------------------------
393  vtkVolumeMapper* vtkNotUsed(mapper),
394  vtkVolume* vtkNotUsed(vol),
395  int vtkNotUsed(numberOfComponents))
396  {
397  if (!ren->GetActiveCamera()->GetParallelProjection())
398  {
399  return std::string(
400  "vec3 computeRayDirection() \n\
401  { \n\
402  return normalize(m_vertex_pos.xyz - g_eye_pos_obj.xyz); \n\
403  }");
404  }
405  else
406  {
407  return std::string(
408  "uniform vec3 m_projection_direction; \n\
409  vec3 computeRayDirection() \n\
410  { \n\
411  return normalize((m_inverse_volume_matrix * \n\
412  vec4(m_projection_direction, 0.0)).xyz); \n\
413  }");
414  }
415  }
416 
417  //--------------------------------------------------------------------------
419  vtkVolumeMapper* vtkNotUsed(mapper),
420  vtkVolume* vtkNotUsed(vol),
421  int numberOfComponents)
422  {
423  if (numberOfComponents == 1)
424  {
425  return std::string(" \n\
426  uniform sampler1D m_color_transfer_func; \n\
427  vec4 computeColor(vec4 scalar) \n\
428  { \n\
429  return computeLighting(vec4(texture1D(m_color_transfer_func, \n\
430  scalar.w).xyz, \n\
431  computeOpacity(scalar))); \n\
432  }");
433  }
434 
435  return std::string(" \n\
436  vec4 computeColor(vec4 scalar) \n\
437  { \n\
438  return computeLighting(vec4(scalar.xyz, computeOpacity(scalar))); \n\
439  }");
440  }
441 
442  //--------------------------------------------------------------------------
444  vtkVolumeMapper* vtkNotUsed(mapper),
445  vtkVolume* vtkNotUsed(vol),
446  int vtkNotUsed(numberOfComponents))
447  {
448  return std::string(
449  "uniform sampler1D m_opacity_transfer_func; \n\
450  float computeOpacity(vec4 scalar) \n\
451  { \n\
452  return texture1D(m_opacity_transfer_func, scalar.w).w; \n\
453  }");
454  }
455 
456  //--------------------------------------------------------------------------
458  vtkVolumeMapper* vtkNotUsed(mapper),
459  vtkVolume* vtkNotUsed(vol))
460  {
461  return std::string("");
462  }
463 
464  //--------------------------------------------------------------------------
466  vtkVolumeMapper* vtkNotUsed(mapper),
467  vtkVolume* vtkNotUsed(vol))
468  {
469  return std::string("");
470  }
471 
472  //--------------------------------------------------------------------------
474  vtkVolumeMapper* mapper,
475  vtkVolume* vol)
476  {
478  {
479  return std::string(
480  "// We get data between 0.0 - 1.0 range \n\
481  vec4 l_max_value = vec4(0.0);");
482  }
484  {
485  return std::string(
486  "// We get data between 0.0 - 1.0 range \n\
487  vec4 l_min_value = vec4(1.0);");
488  }
489  else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
490  {
491  return std::string(
492  "// We get data between 0.0 - 1.0 range \n\
493  float l_sum_value = 0.0;");
494  }
495  else if (vol->GetProperty()->GetShade())
496  {
497  return std::string(
498  "// Light position in object space \n\
499  g_light_pos_obj = (m_inverse_volume_matrix * \n\
500  vec4(m_light_pos, 1.0)); \n\
501  if (g_light_pos_obj.w != 0.0) \n\
502  { \n\
503  g_light_pos_obj.x /= g_light_pos_obj.w; \n\
504  g_light_pos_obj.y /= g_light_pos_obj.w; \n\
505  g_light_pos_obj.z /= g_light_pos_obj.w; \n\
506  g_light_pos_obj.w = 1.0; \n\
507  };");
508  }
509  else
510  {
511  return std::string("");
512  }
513  }
514 
515  //--------------------------------------------------------------------------
517  vtkVolumeMapper* mapper,
518  vtkVolume* vtkNotUsed(vol),
519  vtkImageData* maskInput,
520  vtkVolumeMask* mask, int maskType)
521  {
522  std::string shaderStr = std::string(
523  "if (!l_skip) \n\
524  {\n");
525 
527  {
528  shaderStr += std::string(
529  "vec4 scalar = texture3D(m_volume, g_data_pos); \n\
530  if (l_max_value.w < scalar.w) \n\
531  { \n\
532  l_max_value = scalar; \n\
533  }");
534  }
536  {
537  shaderStr += std::string(
538  "vec4 scalar = texture3D(m_volume, g_data_pos) ; \n\
539  if (l_min_value.w > scalar.w) \n\
540  { \n\
541  l_min_value = scalar; \n\
542  }");
543  }
544  else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
545  {
546  shaderStr += std::string(
547  "vec4 scalar = texture3D(m_volume, g_data_pos); \n\
548  float opacity = computeOpacity(scalar); \n\
549  l_sum_value = l_sum_value + opacity * scalar.w;");
550  }
551  else if (mapper->GetBlendMode() == vtkVolumeMapper::COMPOSITE_BLEND)
552  {
553  if (!mask || !maskInput ||
555  {
556  shaderStr += std::string(
557  "// Data fetching from the red channel of volume texture \n\
558  vec4 scalar = texture3D(m_volume, g_data_pos); \n\
559  vec4 g_src_color = computeColor(scalar);");
560  }
561 
562  shaderStr += std::string(
563  "// Opacity calculation using compositing: \n\
564  // here we use front to back compositing scheme whereby the current \n\
565  // sample value is multiplied to the currently accumulated alpha \n\
566  // and then this product is subtracted from the sample value to \n\
567  // get the alpha from the previous steps. \n\
568  // Next, this alpha is multiplied with the current sample colour \n\
569  // and accumulated to the composited colour. The alpha value from \n\
570  // the previous steps is then accumulated to the composited colour \n\
571  // alpha. \n\
572  g_src_color.rgb *= g_src_color.a; \n\
573  g_frag_color = (1.0f - g_frag_color.a) * g_src_color + g_frag_color;");
574  }
575  else
576  {
577  shaderStr += std::string("");
578  }
579  shaderStr += std::string("}");
580  return shaderStr;
581  }
582 
583  //--------------------------------------------------------------------------
585  vtkVolumeMapper* mapper,
586  vtkVolume* vtkNotUsed(vol))
587  {
589  {
590  return std::string(
591  "vec4 g_src_color = vec4(computeColor(l_max_value).xyz, \n\
592  computeOpacity(l_max_value)); \n\
593  g_frag_color.rgb = g_src_color.rgb * g_src_color.a; \n\
594  g_frag_color.a = g_src_color.a;");
595  }
597  {
598  return std::string(
599  "vec4 g_src_color = vec4(computeColor(l_min_value).xyz, \n\
600  computeOpacity(l_min_value)); \n\
601  g_frag_color.rgb = g_src_color.rgb * g_src_color.a; \n\
602  g_frag_color.a = g_src_color.a;");
603  }
604  else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
605  {
606  return std::string(
607  "l_sum_value = clamp(l_sum_value, 0.0, 1.0); \n\
608  g_frag_color = vec4(vec3(l_sum_value), 1.0);");
609  }
610  else
611  {
612  return std::string("");
613  }
614  }
615 
616  //--------------------------------------------------------------------------
618  vtkVolumeMapper* vtkNotUsed(mapper),
619  vtkVolume* vtkNotUsed(vol))
620  {
621  return std::string("");
622  }
623 
624  //--------------------------------------------------------------------------
626  vtkVolumeMapper* vtkNotUsed(mapper),
627  vtkVolume* vtkNotUsed(vol))
628  {
629  return std::string("");
630  }
631 
632  //--------------------------------------------------------------------------
634  vtkVolumeMapper* vtkNotUsed(mapper),
635  vtkVolume* vtkNotUsed(vol))
636  {
637  return std::string(
638  "// Minimum texture access coordinate \n\
639  const vec3 l_tex_min = vec3(0); \n\
640  \n\
641  // Maximum texture access coordinate \n\
642  const vec3 l_tex_max = vec3(1); \n\
643  \n\
644  // Flag to indicate if the raymarch loop should terminate \n\
645  bool stop = false; \n\
646  \n\
647  // 2D Texture fragment coordinates [0,1] from fragment coordinates \n\
648  // the frame buffer texture has the size of the plain buffer but \n\
649  // we use a fraction of it. The texture coordinates is less than 1 if \n\
650  // the reduction factor is less than 1. \n\
651  // Device coordinates are between -1 and 1. We need texture \n\
652  // coordinates between 0 and 1 the m_depth_sampler buffer has the \n\
653  // original size buffer. \n\
654  vec2 m_frag_tex_coord = \n\
655  (gl_FragCoord.xy - m_window_lower_left_corner) * \n\
656  m_inv_window_size; \n\
657  vec4 l_depth_value = texture2D(m_depth_sampler, m_frag_tex_coord); \n\
658  float m_terminate_point_max = 0.0; \n\
659  \n\
660  // Depth test \n\
661  if(gl_FragCoord.z >= l_depth_value.x) \n\
662  { \n\
663  discard; \n\
664  } \n\
665  \n\
666  // color buffer or max scalar buffer have a reduced size. \n\
667  m_frag_tex_coord = (gl_FragCoord.xy - m_window_lower_left_corner) * \n\
668  m_inv_original_window_size; \n\
669  \n\
670  // Compute max number of iterations it will take before we hit \n\
671  // the termination point \n\
672  \n\
673  // Abscissa of the point on the depth buffer along the ray. \n\
674  // point in texture coordinates \n\
675  vec4 m_terminate_point; \n\
676  m_terminate_point.x = \n\
677  (gl_FragCoord.x - m_window_lower_left_corner.x) * 2.0 * \n\
678  m_inv_window_size.x - 1.0; \n\
679  m_terminate_point.y = \n\
680  (gl_FragCoord.y - m_window_lower_left_corner.y) * 2.0 * \n\
681  m_inv_window_size.y - 1.0; \n\
682  m_terminate_point.z = (2.0 * l_depth_value.x - (gl_DepthRange.near + \n\
683  gl_DepthRange.far)) / gl_DepthRange.diff; \n\
684  m_terminate_point.w = 1.0; \n\
685  \n\
686  // From normalized device coordinates to eye coordinates. \n\
687  // m_projection_matrix is inversed because of way VT \n\
688  // From eye coordinates to texture coordinates \n\
689  m_terminate_point = m_inverse_texture_dataset_matrix * \n\
690  m_inverse_volume_matrix * \n\
691  m_inverse_modelview_matrix * \n\
692  m_inverse_projection_matrix * \n\
693  m_terminate_point; \n\
694  m_terminate_point /= m_terminate_point.w; \n\
695  \n\
696  m_terminate_point_max = \n\
697  length(m_terminate_point.xyz - g_data_pos.xyz) / \n\
698  length(g_dir_step); \n\
699  float m_current_t = 0.0;");
700  }
701 
702  //--------------------------------------------------------------------------
704  vtkVolumeMapper* vtkNotUsed(mapper),
705  vtkVolume* vtkNotUsed(vol))
706  {
707  return std::string(
708  "// The two constants l_tex_min and l_tex_max have a value of \n\
709  // vec3(-1,-1,-1) and vec3(1,1,1) respectively. To determine if the \n\
710  // data value is outside the m_volume data, we use the sign function. \n\
711  // The sign function return -1 if the value is less than 0, 0 if the \n\
712  // value is equal to 0 and 1 if value is greater than 0. Hence, the \n\
713  // sign function for the calculation (sign(g_data_pos-l_tex_min) and \n\
714  // sign (l_tex_max-g_data_pos)) will give us vec3(1,1,1) at the \n\
715  // possible minimum and maximum position. \n\
716  // When we do a dot product between two vec3(1,1,1) we get answer 3. \n\
717  // So to be within the dataset limits, the dot product will return a \n\
718  // value less than 3. If it is greater than 3, we are already out of \n\
719  // the m_volume dataset \n\
720  stop = dot(sign(g_data_pos - l_tex_min), sign(l_tex_max - g_data_pos)) \n\
721  < 3.0; \n\
722  \n\
723  // If the stopping condition is true we brek out of the ray marching \n\
724  // loop \n\
725  if (stop) \n\
726  { \n\
727  break; \n\
728  } \n\
729  // Early ray termination \n\
730  // if the currently composited colour alpha is already fully saturated \n\
731  // we terminated the loop or if we have hit an obstacle in the \n\
732  // direction of they ray (using depth buffer) we terminate as well. \n\
733  if((g_frag_color.a > (1 - 1/255.0)) || \n\
734  m_current_t >= m_terminate_point_max) \n\
735  { \n\
736  break; \n\
737  } \n\
738  ++m_current_t;"
739  );
740  }
741 
742  //--------------------------------------------------------------------------
744  vtkVolumeMapper* vtkNotUsed(mapper),
745  vtkVolume* vtkNotUsed(vol))
746  {
747  return std::string("");
748  }
749 
750  //--------------------------------------------------------------------------
752  vtkVolumeMapper* vtkNotUsed(mapper),
753  vtkVolume* vtkNotUsed(vol))
754  {
755  return std::string("");
756  }
757 
758  //--------------------------------------------------------------------------
760  vtkVolumeMapper* mapper,
761  vtkVolume* vtkNotUsed(vol))
762  {
763  if (!mapper->GetCropping()) {
764  return std::string("");
765  }
766 
767  return std::string("\n\
768  uniform float cropping_planes[6]; \n\
769  uniform int cropping_flags [32]; \n\
770  // X: axis = 0, Y: axis = 1, Z: axis = 2 \n\
771  // cp Cropping plane bounds (minX, maxX, minY, maxY, minZ, maxZ) \n\
772  int computeRegionCoord(float cp[6], vec3 pos, int axis) \n\
773  { \n\
774  int cpmin = axis * 2; \n\
775  int cpmax = cpmin + 1; \n\
776  \n\
777  if (pos[axis] < cp[cpmin]) \n\
778  { \n\
779  return 1; \n\
780  } \n\
781  else if (pos[axis] >= cp[cpmin] && \n\
782  pos[axis] < cp[cpmax]) \n\
783  { \n\
784  return 2; \n\
785  } \n\
786  else if (pos[axis] >= cp[cpmax]) \n\
787  { \n\
788  return 3; \n\
789  } \n\
790  return 0; \n\
791  } \n\
792  \n\
793  int computeRegion(float cp[6], vec3 pos) \n\
794  { \n\
795  return ( computeRegionCoord(cp, pos, 0) + \n\
796  (computeRegionCoord(cp, pos, 1) - 1) * 3 + \n\
797  (computeRegionCoord(cp, pos, 2) - 1) * 9); \n\
798  }");
799  }
800 
801  //--------------------------------------------------------------------------
803  vtkVolumeMapper* mapper,
804  vtkVolume* vtkNotUsed(vol))
805  {
806  if (!mapper->GetCropping()) {
807  return std::string("");
808  }
809 
810  return std::string("\n\
811  // Convert cropping region to texture space \n\
812  float cropping_planes_ts[6];\n\
813  mat4 datasetToTextureMat = m_inverse_texture_dataset_matrix; \n\
814  vec4 temp = vec4(cropping_planes[0], cropping_planes[1], 0.0, 1.0); \n\
815  temp = datasetToTextureMat * temp; \n\
816  if (temp[3] != 0.0) {temp[0] /= temp[3]; temp[1] /= temp[3];} \n\
817  cropping_planes_ts[0] = temp[0];\n\
818  cropping_planes_ts[1] = temp[1];\n\
819  \n\
820  temp = vec4(cropping_planes[2], cropping_planes[3], 0.0, 1.0); \n\
821  temp = datasetToTextureMat * temp; \n\
822  if (temp[3] != 0.0) {temp[0] /= temp[3]; temp[1] /= temp[3];} \n\
823  cropping_planes_ts[2] = temp[0];\n\
824  cropping_planes_ts[3] = temp[1];\n\
825  \n\
826  temp = vec4(cropping_planes[4], cropping_planes[5], 0.0, 1.0); \n\
827  temp = datasetToTextureMat * temp; \n\
828  if (temp[3] != 0.0) {temp[0] /= temp[3]; temp[1] /= temp[3];} \n\
829  cropping_planes_ts[4] = temp[0];\n\
830  cropping_planes_ts[5] = temp[1];");
831  }
832 
833  //--------------------------------------------------------------------------
835  vtkVolumeMapper* mapper,
836  vtkVolume* vtkNotUsed(vol))
837  {
838  if (!mapper->GetCropping()) {
839  return std::string("");
840  }
841 
842  return std::string("\n\
843  // Determine region \n\
844  int regionNo = computeRegion(cropping_planes_ts, g_data_pos); \n\
845  \n\
846  // Do & operation with cropping flags \n\
847  // Pass the flag that its Ok to sample or not to sample \n\
848  if (cropping_flags[regionNo] == 0) \n\
849  { \n\
850  // Skip this voxel \n\
851  l_skip = true; \n\
852  }");
853  }
854 
855  //--------------------------------------------------------------------------
857  vtkVolumeMapper* vtkNotUsed(mapper),
858  vtkVolume* vtkNotUsed(vol))
859  {
860  return std::string("");
861  }
862 
863  //--------------------------------------------------------------------------
865  vtkVolumeMapper* vtkNotUsed(mapper),
866  vtkVolume* vtkNotUsed(vol))
867  {
868  return std::string("");
869  }
870 
871  //--------------------------------------------------------------------------
873  vtkVolumeMapper* vtkNotUsed(mapper),
874  vtkVolume* vtkNotUsed(vol))
875  {
876  return std::string("");
877  }
878 
879  //--------------------------------------------------------------------------
881  vtkVolumeMapper* mapper,
882  vtkVolume* vtkNotUsed(vol))
883  {
884  if (!mapper->GetClippingPlanes())
885  {
886  return std::string("");
887  }
888  else
889  {
890  return std::string("\n\
891  float clipping_planes_ts[48];\n\
892  int clipping_planes_size = int(m_clipping_planes[0]);\n\
893  \n\
894  mat4 world_to_texture_mat = m_inverse_texture_dataset_matrix *\n\
895  m_inverse_volume_matrix;\n\
896  for (int i = 0; i < clipping_planes_size; i = i + 6)\n\
897  {\n\
898  vec4 origin = vec4(m_clipping_planes[i + 1],\n\
899  m_clipping_planes[i + 2],\n\
900  m_clipping_planes[i + 3], 1.0);\n\
901  vec4 normal = vec4(m_clipping_planes[i + 4],\n\
902  m_clipping_planes[i + 5],\n\
903  m_clipping_planes[i + 6], 0.0);\n\
904  \n\
905  origin = world_to_texture_mat * origin;\n\
906  normal = world_to_texture_mat * normal;\n\
907  \n\
908  if (origin[3] != 0.0)\n\
909  {\n\
910  origin[0] = origin[0] / origin[3];\n\
911  origin[1] = origin[1] / origin[3];\n\
912  origin[2] = origin[2] / origin[3];\n\
913  }\n\
914  if (normal[3] != 0.0)\n\
915  {\n\
916  normal[0] = normal[0] / normal[3];\n\
917  normal[1] = normal[1] / normal[3];\n\
918  normal[2] = normal[2] / normal[3];\n\
919  }\n\
920  \n\
921  clipping_planes_ts[i] = origin[0];\n\
922  clipping_planes_ts[i + 1] = origin[1];\n\
923  clipping_planes_ts[i + 2] = origin[2];\n\
924  \n\
925  clipping_planes_ts[i + 3] = normal[0];\n\
926  clipping_planes_ts[i + 4] = normal[1];\n\
927  clipping_planes_ts[i + 5] = normal[2];\n\
928  }");
929  }
930  }
931 
932  //--------------------------------------------------------------------------
934  vtkVolumeMapper* mapper,
935  vtkVolume* vtkNotUsed(vol))
936  {
937  if (!mapper->GetClippingPlanes())
938  {
939  return std::string("");
940  }
941  else
942  {
943  return std::string("\n\
944  for (int i = 0; i < (clipping_planes_size) && !l_skip; i = i + 6)\n\
945  {\n\
946  if (dot(vec3(g_data_pos - vec3(clipping_planes_ts[i],\n\
947  clipping_planes_ts[i + 1],\n\
948  clipping_planes_ts[i + 2])),\n\
949  vec3(clipping_planes_ts[i + 3],\n\
950  clipping_planes_ts[i + 4],\n\
951  clipping_planes_ts[i + 5])) < 0)\n\
952  {\n\
953  l_skip = true;\n\
954  break;\n\
955  }\n\
956  }");
957  }
958  }
959 
960  //--------------------------------------------------------------------------
962  vtkVolumeMapper* vtkNotUsed(mapper),
963  vtkVolume* vtkNotUsed(vol))
964  {
965  return std::string("");
966  }
967 
968  //--------------------------------------------------------------------------
970  vtkVolumeMapper* vtkNotUsed(mapper),
971  vtkVolume* vtkNotUsed(vol),
972  vtkImageData* maskInput,
974  int vtkNotUsed(maskType))
975  {
976  if (!mask || !maskInput)
977  {
978  return std::string("");
979  }
980  else
981  {
982  return std::string("uniform sampler3D m_mask;");
983  }
984  }
985 
986  //--------------------------------------------------------------------------
988  vtkVolumeMapper* vtkNotUsed(mapper),
989  vtkVolume* vtkNotUsed(vol),
990  vtkImageData* maskInput,
991  vtkVolumeMask* mask,
992  int maskType)
993  {
994  if (!mask || !maskInput ||
996  {
997  return std::string("");
998  }
999  else
1000  {
1001  return std::string("\n\
1002  vec4 maskValue = texture3D(m_mask, g_data_pos);\n\
1003  if(maskValue.a <= 0.0)\n\
1004  {\n\
1005  l_skip = true;\n\
1006  }");
1007  }
1008  }
1009 
1010  //--------------------------------------------------------------------------
1012  vtkVolumeMapper* vtkNotUsed(mapper),
1013  vtkVolume* vtkNotUsed(vol),
1014  vtkImageData* maskInput,
1015  vtkVolumeMask* mask,
1016  int maskType)
1017  {
1018  if (!mask || !maskInput ||
1020  {
1021  return std::string("");
1022  }
1023  else
1024  {
1025  return std::string("\n\
1026  uniform float m_mask_blendfactor;\n\
1027  uniform sampler1D m_mask_1;\n\
1028  uniform sampler1D m_mask_2;");
1029  }
1030  }
1031 
1032  //--------------------------------------------------------------------------
1034  vtkVolumeMapper* vtkNotUsed(mapper),
1035  vtkVolume* vtkNotUsed(vol),
1036  vtkImageData* maskInput,
1037  vtkVolumeMask* mask,
1038  int maskType)
1039  {
1040  if (!mask || !maskInput ||
1042  {
1043  return std::string("");
1044  }
1045  else
1046  {
1047  return std::string("\n\
1048  vec4 scalar = texture3D(m_volume, g_data_pos); \n\
1049  if (m_mask_blendfactor == 0.0)\n\
1050  {\n\
1051  g_src_color = computeColor(scalar);\n\
1052  }\n\
1053  else\n\
1054  {\n\
1055  // Get the mask value at this same location\n\
1056  vec4 maskValue = texture3D(m_mask, g_data_pos);\n\
1057  if(maskValue.a == 0.0)\n\
1058  {\n\
1059  g_src_color = computeColor(scalar);\n\
1060  }\n\
1061  else\n\
1062  {\n\
1063  if (maskValue.a == 1.0/255.0)\n\
1064  {\n\
1065  g_src_color = texture1D(m_mask_1, scalar.w);\n\
1066  }\n\
1067  else\n\
1068  {\n\
1069  // maskValue.a == 2.0/255.0\n\
1070  g_src_color = texture1D(m_mask_2, scalar.w);\n\
1071  }\n\
1072  g_src_color.a = 1.0; \n\
1073  if(m_mask_blendfactor < 1.0) \n\
1074  {\n\
1075  g_src_color = (1.0 - m_mask_blendfactor) * computeColor(scalar)\n\
1076  + m_mask_blendfactor * g_src_color;\n\
1077  }\n\
1078  }\n\
1079  g_src_color.a = computeOpacity(scalar); \n\
1080  }");
1081  }
1082  }
1083 }
1084 
1085 #endif // _vtkVolumeShaderComposer_h
1086 // VTK-HeaderTest-Exclude: vtkVolumeShaderComposer.h
std::string ShadingExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents=0)
#define vtkNotUsed(x)
Definition: vtkSetGet.h:547
const GLint * first
Definition: vtkgl.h:11686
represents a volume (data & properties) in a rendered scene
Definition: vtkVolume.h:49
Abstract class for a volume mapper.
std::string ClippingIncrement(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
virtual int GetBlendMode()
GLenum GLint GLuint mask
Definition: vtkgl.h:11980
std::string ComputeTextureCoords(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string CompositeMaskGlobalsFrag(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeMask *mask, int maskType)
std::string CompositeMaskIncrement(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeMask *mask, int maskType)
abstract specification for renderers
Definition: vtkRenderer.h:63
std::string TerminationExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string GradientsComputeFunc(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vol, int noOfComponents, int independentComponents, std::map< int, std::string > gradientTableMap)
std::string BaseInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string TerminationIncrement(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
virtual vtkPlaneCollection * GetClippingPlanes()
vtkCamera * GetActiveCamera()
std::string CroppingGlobalsFrag(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string BaseGlobalsVert(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
int GetShade(int index)
std::string CroppingGlobalsVert(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string BinaryMaskIncrement(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeMask *mask, int maskType)
std::string TerminationInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
virtual int GetDisableGradientOpacity(int index)
std::string ClippingExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string RayDirectionFunc(vtkRenderer *ren, vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int vtkNotUsed(noOfComponents))
topologically and geometrically regular array of data
Definition: vtkImageData.h:44
std::string ClippingGlobalsVert(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ColorTransferFunc(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, std::map< int, std::string > colorTableMap)
std::string ShadingGlobalsFrag(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ShadingGlobalsVert(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string OpacityTransferFunc(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, std::map< int, std::string > opacityTableMap)
std::string CroppingIncrement(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
virtual int GetParallelProjection()
std::string BaseIncrement(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
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 ClippingGlobalsFrag(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string TerminationGlobalsVert(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 ShadingIncrement(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeMask *mask, int maskType, int noOfComponents, int independentComponents=0)
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 TerminationGlobalsFrag(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string BaseGlobalsFrag(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int vtkNotUsed(numberOfLights), int lightingComplexity, int noOfComponents, int independentComponents)
std::string BaseExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
GLsizei const GLchar ** string
Definition: vtkgl.h:12011
std::string LightComputeFunc(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vol, int noOfComponents, int independentComponents, int vtkNotUsed(numberOfLights), int lightingComplexity)
std::string ComputeClip(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string BinaryMaskGlobalsFrag(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeMask *mask, int vtkNotUsed(maskType))