VTK
/Users/kitware/Dashboards/MyTests/VTK_BLD_Release_docs/Utilities/Doxygen/dox/Rendering/VolumeOpenGLNew/vtkVolumeShaderComposer.h
Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program:   Visualization Toolkit
00004   Module:    vtkVolumeShaderComposer.h
00005 
00006   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
00007   All rights reserved.
00008   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
00009 
00010      This software is distributed WITHOUT ANY WARRANTY; without even
00011      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00012      PURPOSE.  See the above copyright notice for more information.
00013 
00014 =========================================================================*/
00015 
00016 #ifndef _vtkVolumeShaderComposer_h
00017 #define _vtkVolumeShaderComposer_h
00018 
00019 #include "vtkVolumeMask.h"
00020 
00021 #include <vtkCamera.h>
00022 #include <vtkRenderer.h>
00023 #include <vtkVolume.h>
00024 #include <vtkVolumeMapper.h>
00025 #include <vtkVolumeProperty.h>
00026 
00027 #include <string>
00028 
00029 namespace vtkvolume
00030 {
00031   //--------------------------------------------------------------------------
00032   std::string replace(std::string source, const std::string &search,
00033                       const std::string replace, bool all)
00034     {
00035     std::string::size_type pos = 0;
00036     bool first = true;
00037     while ((pos = source.find(search, 0)) != std::string::npos)
00038       {
00039       source.replace(pos, search.length(), replace);
00040       pos += search.length();
00041       if (first)
00042         {
00043         first = false;
00044         if (!all)
00045           {
00046           return source;
00047           }
00048         }
00049       }
00050     return source;
00051     }
00052 
00053   //--------------------------------------------------------------------------
00054   std::string ComputeClip(vtkRenderer* vtkNotUsed(ren),
00055                           vtkVolumeMapper* vtkNotUsed(mapper),
00056                           vtkVolume* vtkNotUsed(vol))
00057     {
00058     return std::string(
00059       "mat4 ogl_projection_matrix = m_projection_matrix; \n\
00060       mat4 ogl_modelview_matrix = m_modelview_matrix; \n\
00061       vec4 pos = ogl_projection_matrix * ogl_modelview_matrix * \n\
00062                  m_volume_matrix * vec4(m_in_vertex_pos.xyz, 1); \n\
00063       gl_Position = pos;"
00064     );
00065     }
00066 
00067   //--------------------------------------------------------------------------
00068   std::string ComputeTextureCoords(vtkRenderer* vtkNotUsed(ren),
00069                                    vtkVolumeMapper* vtkNotUsed(mapper),
00070                                    vtkVolume* vtkNotUsed(vol))
00071     {
00072     return std::string(
00073       "// Assuming point data only. Also, we offset the texture coordinate \n\
00074        // to account for OpenGL treating voxel at the center of the cell. \n\
00075        vec3 uvx = (m_in_vertex_pos - m_vol_extents_min) / \n\
00076                   (m_vol_extents_max - m_vol_extents_min); \n\
00077        vec3 delta = m_texture_extents_max - m_texture_extents_min; \n\
00078        m_texture_coords = (uvx * (delta - vec3(1.0)) + vec3(0.5)) / delta;"
00079     );
00080     }
00081 
00082   //--------------------------------------------------------------------------
00083   std::string BaseGlobalsVert(vtkRenderer* vtkNotUsed(ren),
00084                               vtkVolumeMapper* vtkNotUsed(mapper),
00085                               vtkVolume* vtkNotUsed(vol))
00086     { return std::string(
00087     "uniform mat4 m_modelview_matrix; \n\
00088     uniform mat4 m_projection_matrix; \n\
00089     uniform mat4 m_volume_matrix; \n\
00090     \n\
00091     uniform vec3 m_vol_extents_min; \n\
00092     uniform vec3 m_vol_extents_max; \n\
00093     \n\
00094     uniform vec3 m_texture_extents_max; \n\
00095     uniform vec3 m_texture_extents_min;"
00096     );
00097     }
00098 
00099   //--------------------------------------------------------------------------
00100   std::string BaseGlobalsFrag(vtkRenderer* vtkNotUsed(ren),
00101                               vtkVolumeMapper* vtkNotUsed(mapper),
00102                               vtkVolume* vtkNotUsed(vol))
00103     {
00104     return std::string(
00105       "// Volume dataset \n\
00106       uniform sampler3D m_volume; \n\
00107       \n\
00108       uniform sampler2D m_noise_sampler; \n\
00109       uniform sampler2D m_depth_sampler; \n\
00110       \n\
00111       // Camera position \n\
00112       uniform vec3 m_camera_pos; \n\
00113       uniform vec3 m_light_pos; \n\
00114       \n\
00115       // view and model matrices \n\
00116       uniform mat4 m_volume_matrix; \n\
00117       uniform mat4 m_inverse_volume_matrix; \n\
00118       uniform mat4 m_projection_matrix; \n\
00119       uniform mat4 m_inverse_projection_matrix; \n\
00120       uniform mat4 m_modelview_matrix; \n\
00121       uniform mat4 m_inverse_modelview_matrix; \n\
00122       uniform mat4 m_texture_dataset_matrix; \n\
00123       uniform mat4 m_inverse_texture_dataset_matrix; \n\
00124       \n\
00125       // Ray step size \n\
00126       uniform vec3 m_cell_step; \n\
00127       uniform vec2 m_scalars_range; \n\
00128       uniform vec3 m_cell_spacing; \n\
00129       \n\
00130       // Sample distance \n\
00131       uniform float m_sample_distance; \n\
00132       \n\
00133       // Scales \n\
00134       uniform vec3 m_cell_scale; \n\
00135       uniform vec2 m_window_lower_left_corner; \n\
00136       uniform vec2 m_inv_original_window_size; \n\
00137       uniform vec2 m_inv_window_size; \n\
00138       uniform vec3 m_texture_extents_max; \n\
00139       uniform vec3 m_texture_extents_min; \n\
00140       \n\
00141       // Material and lighting \n\
00142       uniform vec3 m_diffuse; \n\
00143       uniform vec3 m_ambient; \n\
00144       uniform vec3 m_specular; \n\
00145       uniform float m_shininess; \n\
00146       // Other useful variales; \n\
00147       vec4 g_src_color; \n\
00148       vec4 g_light_pos_obj; \n\
00149       vec4 g_eye_pos_obj; ");
00150     }
00151 
00152   //--------------------------------------------------------------------------
00153   std::string BaseInit(vtkRenderer* vtkNotUsed(ren),
00154                        vtkVolumeMapper* vtkNotUsed(mapper),
00155                        vtkVolume* vtkNotUsed(vol))
00156     {
00157     return std::string(
00158       "g_light_pos_obj; \n\
00159       \n\
00160       // Get the 3D texture coordinates for lookup into the m_volume dataset \n\
00161       g_data_pos = m_texture_coords.xyz; \n\
00162       \n\
00163       // Eye position in object space  \n\
00164       g_eye_pos_obj = (m_inverse_volume_matrix * vec4(m_camera_pos, 1.0)); \n\
00165       if (g_eye_pos_obj.w != 0.0) \n\
00166         { \n\
00167         g_eye_pos_obj.x /= g_eye_pos_obj.w; \n\
00168         g_eye_pos_obj.y /= g_eye_pos_obj.w; \n\
00169         g_eye_pos_obj.z /= g_eye_pos_obj.w; \n\
00170         g_eye_pos_obj.w = 1.0; \n\
00171         } \n\
00172       \n\
00173       // Getting the ray marching direction (in object space); \n\
00174       vec3 geom_dir = computeRayDirection(); \n\
00175       \n\
00176       // Multiply the raymarching direction with the step size to get the \n\
00177       // sub-step size we need to take at each raymarching step  \n\
00178       g_dir_step = (m_inverse_texture_dataset_matrix * \n\
00179                     vec4(geom_dir, 0.0)).xyz * m_sample_distance; \n\
00180       \n\
00181       g_data_pos += g_dir_step * texture2D(m_noise_sampler, g_data_pos.xy).x;\n\
00182       \n\
00183       // Flag to deternmine if voxel should be considered for the rendering \n\
00184       bool l_skip = false;");
00185     }
00186 
00187   //--------------------------------------------------------------------------
00188   std::string BaseIncrement(vtkRenderer* vtkNotUsed(ren),
00189                             vtkVolumeMapper* vtkNotUsed(mapper),
00190                             vtkVolume* vtkNotUsed(vol))
00191     {
00192     return std::string("\n\
00193                        l_skip = false;");
00194     }
00195 
00196   //--------------------------------------------------------------------------
00197   std::string BaseExit(vtkRenderer* vtkNotUsed(ren),
00198                        vtkVolumeMapper* vtkNotUsed(mapper),
00199                        vtkVolume* vtkNotUsed(vol))
00200     {
00201     return std::string("");
00202     }
00203 
00204   //--------------------------------------------------------------------------
00205   std::string GradientsComputeFunc(vtkRenderer* vtkNotUsed(ren),
00206                                    vtkVolumeMapper* vtkNotUsed(mapper),
00207                                    vtkVolume* vol,
00208                                    int vtkNotUsed(numberOfComponents))
00209   {
00210     if (vol->GetProperty()->GetShade() &&
00211         vol->GetProperty()->GetDisableGradientOpacity())
00212       {
00213       return std::string(" \n\
00214         vec3 computeGradient() \n\
00215           { \n\
00216           vec3 g1; \n\
00217           vec3 g2; \n\
00218           vec3 xvec = vec3(m_cell_step[0], 0.0, 0.0); \n\
00219           vec3 yvec = vec3(0.0, m_cell_step[1], 0.0); \n\
00220           vec3 zvec = vec3(0.0, 0.0, m_cell_step[2]); \n\
00221           g1.x = texture3D(m_volume, vec3(g_data_pos + xvec)).x; \n\
00222           g1.y = texture3D(m_volume, vec3(g_data_pos + yvec)).x; \n\
00223           g1.z = texture3D(m_volume, vec3(g_data_pos + zvec)).x; \n\
00224           g2.x = texture3D(m_volume, vec3(g_data_pos - xvec)).x; \n\
00225           g2.y = texture3D(m_volume, vec3(g_data_pos - yvec)).x; \n\
00226           g2.z = texture3D(m_volume, vec3(g_data_pos - zvec)).x; \n\
00227           return (g1 - g2); \n\
00228          }");
00229     }
00230     else if (vol->GetProperty()->GetShade() &&
00231              !vol->GetProperty()->GetDisableGradientOpacity())
00232       {
00233       return std::string(" \n\
00234         vec3 computeGradient() \n\
00235           { \n\
00236           vec3 g1; \n\
00237           vec3 g2; \n\
00238           vec3 xvec = vec3(m_cell_step[0], 0.0, 0.0); \n\
00239           vec3 yvec = vec3(0.0, m_cell_step[1], 0.0); \n\
00240           vec3 zvec = vec3(0.0, 0.0, m_cell_step[2]); \n\
00241           g1.x = texture3D(m_volume, vec3(g_data_pos + xvec)).x; \n\
00242           g1.y = texture3D(m_volume, vec3(g_data_pos + yvec)).x; \n\
00243           g1.z = texture3D(m_volume, vec3(g_data_pos + zvec)).x; \n\
00244           g2.x = texture3D(m_volume, vec3(g_data_pos - xvec)).x; \n\
00245           g2.y = texture3D(m_volume, vec3(g_data_pos - yvec)).x; \n\
00246           g2.z = texture3D(m_volume, vec3(g_data_pos - zvec)).x; \n\
00247           g1.x = m_scalars_range[0] + ( \n\
00248                  m_scalars_range[1] - m_scalars_range[0]) * g1.x; \n\
00249           g1.y = m_scalars_range[0] + ( \n\
00250                  m_scalars_range[1] - m_scalars_range[0]) * g1.y; \n\
00251           g1.z = m_scalars_range[0] + ( \n\
00252                  m_scalars_range[1] - m_scalars_range[0]) * g1.z; \n\
00253           g2.x = m_scalars_range[0] + ( \n\
00254                  m_scalars_range[1] - m_scalars_range[0]) * g2.x; \n\
00255           g2.y = m_scalars_range[0] + ( \n\
00256                  m_scalars_range[1] - m_scalars_range[0]) * g2.y; \n\
00257           g2.z = m_scalars_range[0] + ( \n\
00258                  m_scalars_range[1] - m_scalars_range[0]) * g2.z; \n\
00259           g2 = g1 - g2; \n\
00260           return g2; \n\
00261           }");
00262       }
00263     else
00264       {
00265       return std::string(
00266         "vec3 computeGradient() \n\
00267            { \n\
00268              return vec3(0.0); \n\
00269            }");
00270       }
00271   }
00272 
00273   //--------------------------------------------------------------------------
00274   std::string LightComputeFunc(vtkRenderer*vtkNotUsed(ren),
00275                                vtkVolumeMapper* vtkNotUsed(mapper),
00276                                vtkVolume* vol,
00277                                int vtkNotUsed(numberOfComponents))
00278     {
00279     vtkVolumeProperty* volProperty = vol->GetProperty();
00280     if (volProperty->GetShade() &&
00281         volProperty->GetDisableGradientOpacity())
00282       {
00283       return std::string(" \n\
00284         vec4 computeLighting(vec4 color) \n\
00285           {\n\
00286           vec3 ldir = normalize(g_light_pos_obj.xyz - m_vertex_pos); \n\
00287           vec3 vdir = normalize(g_eye_pos_obj.xyz - m_vertex_pos); \n\
00288           vec3 h = normalize(ldir + vdir); \n\
00289           vec3 g2 = computeGradient(); \n\
00290           g2 = (1.0/m_cell_spacing) * g2; \n\
00291           float normalLength = length(g2);\n\
00292           if (normalLength > 0.0) \n\
00293              { \n\
00294              g2 = normalize(g2); \n\
00295              } \n\
00296            else \n\
00297              { \n\
00298              g2 = vec3(0.0, 0.0, 0.0); \n\
00299              } \n\
00300           vec3 final_color = vec3(0.0); \n\
00301           float n_dot_l = dot(g2, ldir); \n\
00302           float n_dot_h = dot(g2, h); \n\
00303           if (n_dot_l < 0.0) \n\
00304             { \n\
00305             n_dot_l = -n_dot_l; \n\
00306             } \n\
00307           if (n_dot_h < 0.0) \n\
00308             { \n\
00309             n_dot_h = -n_dot_h; \n\
00310             } \n\
00311           final_color += m_ambient * color.rgb; \n\
00312           if (n_dot_l > 0) { \n\
00313             final_color += m_diffuse * n_dot_l * color.rgb; \n\
00314            } \n\
00315           final_color += m_specular * pow(n_dot_h, m_shininess); \n\
00316           final_color = clamp(final_color, vec3(0.0), vec3(1.0)); \n\
00317           return vec4(final_color, color.a); \n\
00318           }");
00319       }
00320     else if (volProperty->GetShade() &&
00321         !volProperty->GetDisableGradientOpacity())
00322       {
00323       return std::string(" \n\
00324         uniform sampler1D m_gradient_transfer_func; \n\
00325         vec4 computeLighting(vec4 color) \n\
00326           { \n\
00327           vec3 grad = computeGradient(); \n\
00328           vec3 m_spacing = vec3(m_cell_spacing[0], \n\
00329                                 m_cell_spacing[1], \n\
00330                                 m_cell_spacing[2]); \n\
00331           vec3 aspect; \n\
00332           float avg_spacing = (m_spacing[0] + \n\
00333                                m_spacing[1] + \n\
00334                                m_spacing[2])/3.0; \n\
00335           // Adjust the aspect \n\
00336           aspect.x = m_spacing[0] * 2.0 / avg_spacing; \n\
00337           aspect.y = m_spacing[1] * 2.0 / avg_spacing; \n\
00338           aspect.z = m_spacing[2] * 2.0 / avg_spacing; \n\
00339           grad.x /= aspect.x; \n\
00340           grad.y /= aspect.y; \n\
00341           grad.z /= aspect.z; \n\
00342           float grad_mag = sqrt(grad.x * grad.x  + \n\
00343                                 grad.y * grad.y + \n\
00344                                 grad.z * grad.z); \n\
00345           if (grad_mag > 0.0) \n\
00346              { \n\
00347              grad.x /= grad_mag; \n\
00348              grad.y /= grad_mag; \n\
00349              grad.z /= grad_mag; \n\
00350              } \n\
00351            else \n\
00352              { \n\
00353              grad = vec3(0.0, 0.0, 0.0); \n\
00354              } \n\
00355           grad_mag = grad_mag * 1.0 / (0.25 * (m_scalars_range[1] - \n\
00356                                               (m_scalars_range[0]))); \n\
00357           grad_mag = clamp(grad_mag, 0.0, 1.0); \n\
00358           vec4 final_color = vec4(0.0); \n\
00359           vec3 ldir = normalize(g_light_pos_obj.xyz - m_vertex_pos); \n\
00360           vec3 vdir = normalize(g_eye_pos_obj.xyz - m_vertex_pos); \n\
00361           vec3 h = normalize(ldir + vdir); \n\
00362           float n_dot_l = dot(grad, ldir); \n\
00363           float n_dot_h = dot(grad, h); \n\
00364           if (n_dot_l < 0.0) \n\
00365             { \n\
00366             n_dot_l = -n_dot_l; \n\
00367             } \n\
00368           if (n_dot_h < 0.0) \n\
00369             { \n\
00370             n_dot_h = -n_dot_h; \n\
00371             } \n\
00372           final_color.rgb += m_ambient; \n\
00373           final_color.rgb += m_diffuse * n_dot_l * color.rgb; \n\
00374           final_color.rgb += m_specular * pow(n_dot_h, m_shininess); \n\
00375           final_color.rgb = clamp(final_color.rgb, vec3(0.0), vec3(1.0)); \n\
00376           final_color.a = color.a * \n\
00377                           texture1D(m_gradient_transfer_func, grad_mag).w; \n\
00378           return final_color; \n\
00379           }");
00380       }
00381     else
00382       {
00383       return std::string(
00384         "vec4 computeLighting(vec4 color) \n\
00385            { \n\
00386            return color; \n\
00387            }");
00388       }
00389     }
00390 
00391   //--------------------------------------------------------------------------
00392   std::string RayDirectionFunc(vtkRenderer* ren,
00393                                vtkVolumeMapper* vtkNotUsed(mapper),
00394                                vtkVolume* vtkNotUsed(vol),
00395                                int vtkNotUsed(numberOfComponents))
00396     {
00397     if (!ren->GetActiveCamera()->GetParallelProjection())
00398       {
00399       return std::string(
00400         "vec3 computeRayDirection() \n\
00401            { \n\
00402            return normalize(m_vertex_pos.xyz - g_eye_pos_obj.xyz); \n\
00403            }");
00404       }
00405     else
00406       {
00407       return std::string(
00408         "uniform vec3 m_projection_direction; \n\
00409          vec3 computeRayDirection() \n\
00410            { \n\
00411            return normalize((m_inverse_volume_matrix * \n\
00412                              vec4(m_projection_direction, 0.0)).xyz); \n\
00413            }");
00414       }
00415     }
00416 
00417   //--------------------------------------------------------------------------
00418   std::string ColorTransferFunc(vtkRenderer* vtkNotUsed(ren),
00419                                 vtkVolumeMapper* vtkNotUsed(mapper),
00420                                 vtkVolume* vtkNotUsed(vol),
00421                                 int numberOfComponents)
00422     {
00423       if (numberOfComponents == 1)
00424         {
00425         return std::string(" \n\
00426           uniform sampler1D m_color_transfer_func; \n\
00427           vec4 computeColor(vec4 scalar) \n\
00428             { \n\
00429             return computeLighting(vec4(texture1D(m_color_transfer_func, \n\
00430                                                   scalar.w).xyz, \n\
00431                                         computeOpacity(scalar))); \n\
00432             }");
00433         }
00434 
00435         return std::string(" \n\
00436           vec4 computeColor(vec4 scalar) \n\
00437           { \n\
00438           return computeLighting(vec4(scalar.xyz, computeOpacity(scalar))); \n\
00439           }");
00440     }
00441 
00442   //--------------------------------------------------------------------------
00443   std::string OpacityTransferFunc(vtkRenderer* vtkNotUsed(ren),
00444                                   vtkVolumeMapper* vtkNotUsed(mapper),
00445                                   vtkVolume* vtkNotUsed(vol),
00446                                   int vtkNotUsed(numberOfComponents))
00447     {
00448     return std::string(
00449       "uniform sampler1D m_opacity_transfer_func; \n\
00450        float computeOpacity(vec4 scalar) \n\
00451          { \n\
00452          return texture1D(m_opacity_transfer_func, scalar.w).w; \n\
00453          }");
00454     }
00455 
00456   //--------------------------------------------------------------------------
00457   std::string ShadingGlobalsVert(vtkRenderer* vtkNotUsed(ren),
00458                                  vtkVolumeMapper* vtkNotUsed(mapper),
00459                                  vtkVolume* vtkNotUsed(vol))
00460     {
00461     return std::string("");
00462     }
00463 
00464   //--------------------------------------------------------------------------
00465   std::string ShadingGlobalsFrag(vtkRenderer* vtkNotUsed(ren),
00466                                  vtkVolumeMapper* vtkNotUsed(mapper),
00467                                  vtkVolume* vtkNotUsed(vol))
00468     {
00469     return std::string("");
00470     }
00471 
00472   //--------------------------------------------------------------------------
00473   std::string ShadingInit(vtkRenderer* vtkNotUsed(ren),
00474                           vtkVolumeMapper* mapper,
00475                           vtkVolume* vol)
00476     {
00477     if (mapper->GetBlendMode() == vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND)
00478       {
00479       return std::string(
00480         "// We get data between 0.0 - 1.0 range \n\
00481          vec4 l_max_value = vec4(0.0);");
00482       }
00483     else if (mapper->GetBlendMode() == vtkVolumeMapper::MINIMUM_INTENSITY_BLEND)
00484       {
00485       return std::string(
00486         "// We get data between 0.0 - 1.0 range \n\
00487         vec4 l_min_value = vec4(1.0);");
00488       }
00489     else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
00490       {
00491       return std::string(
00492         "// We get data between 0.0 - 1.0 range \n\
00493         float l_sum_value = 0.0;");
00494       }
00495     else if (vol->GetProperty()->GetShade())
00496       {
00497       return std::string(
00498         "// Light position in object space \n\
00499          g_light_pos_obj = (m_inverse_volume_matrix * \n\
00500                             vec4(m_light_pos, 1.0)); \n\
00501          if (g_light_pos_obj.w != 0.0) \n\
00502           { \n\
00503           g_light_pos_obj.x /= g_light_pos_obj.w; \n\
00504           g_light_pos_obj.y /= g_light_pos_obj.w; \n\
00505           g_light_pos_obj.z /= g_light_pos_obj.w; \n\
00506           g_light_pos_obj.w = 1.0; \n\
00507           };");
00508       }
00509     else
00510       {
00511       return std::string("");
00512       }
00513     }
00514 
00515   //--------------------------------------------------------------------------
00516   std::string ShadingIncrement(vtkRenderer* vtkNotUsed(ren),
00517                                vtkVolumeMapper* mapper,
00518                                vtkVolume* vtkNotUsed(vol),
00519                                vtkImageData* maskInput,
00520                                vtkVolumeMask* mask, int maskType)
00521     {
00522     std::string shaderStr = std::string(
00523       "if (!l_skip) \n\
00524          {\n");
00525 
00526     if (mapper->GetBlendMode() == vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND)
00527       {
00528       shaderStr += std::string(
00529         "vec4 scalar = texture3D(m_volume, g_data_pos); \n\
00530          if (l_max_value.w < scalar.w) \n\
00531            { \n\
00532            l_max_value = scalar; \n\
00533            }");
00534       }
00535     else if (mapper->GetBlendMode() == vtkVolumeMapper::MINIMUM_INTENSITY_BLEND)
00536       {
00537       shaderStr += std::string(
00538         "vec4 scalar = texture3D(m_volume, g_data_pos) ; \n\
00539           if (l_min_value.w > scalar.w) \n\
00540             { \n\
00541             l_min_value = scalar; \n\
00542             }");
00543       }
00544     else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
00545       {
00546       shaderStr += std::string(
00547         "vec4 scalar = texture3D(m_volume, g_data_pos); \n\
00548         float opacity = computeOpacity(scalar); \n\
00549         l_sum_value = l_sum_value + opacity * scalar.w;");
00550       }
00551     else if (mapper->GetBlendMode() == vtkVolumeMapper::COMPOSITE_BLEND)
00552       {
00553       if (!mask || !maskInput ||
00554           maskType != vtkGPUVolumeRayCastMapper::LabelMapMaskType)
00555         {
00556         shaderStr += std::string(
00557           "// Data fetching from the red channel of volume texture \n\
00558           vec4 scalar = texture3D(m_volume, g_data_pos); \n\
00559           vec4 g_src_color = computeColor(scalar);");
00560         }
00561 
00562       shaderStr += std::string(
00563         "// Opacity calculation using compositing: \n\
00564          // here we use front to back compositing scheme whereby the current \n\
00565          // sample value is multiplied to the currently accumulated alpha \n\
00566          // and then this product is subtracted from the sample value to \n\
00567          // get the alpha from the previous steps. \n\
00568          // Next, this alpha is multiplied with the current sample colour \n\
00569          // and accumulated to the composited colour. The alpha value from \n\
00570          // the previous steps is then accumulated to the composited colour \n\
00571          // alpha. \n\
00572          g_src_color.rgb *= g_src_color.a; \n\
00573          g_frag_color = (1.0f - g_frag_color.a) * g_src_color + g_frag_color;");
00574       }
00575      else
00576        {
00577        shaderStr += std::string("");
00578        }
00579       shaderStr += std::string("}");
00580       return shaderStr;
00581     }
00582 
00583   //--------------------------------------------------------------------------
00584   std::string ShadingExit(vtkRenderer* vtkNotUsed(ren),
00585                           vtkVolumeMapper* mapper,
00586                           vtkVolume* vtkNotUsed(vol))
00587     {
00588     if (mapper->GetBlendMode() == vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND)
00589       {
00590       return std::string(
00591        "vec4 g_src_color = vec4(computeColor(l_max_value).xyz, \n\
00592                                 computeOpacity(l_max_value)); \n\
00593         g_frag_color.rgb = g_src_color.rgb * g_src_color.a; \n\
00594         g_frag_color.a = g_src_color.a;");
00595       }
00596     else if (mapper->GetBlendMode() == vtkVolumeMapper::MINIMUM_INTENSITY_BLEND)
00597       {
00598       return std::string(
00599         "vec4 g_src_color = vec4(computeColor(l_min_value).xyz, \n\
00600                                  computeOpacity(l_min_value)); \n\
00601         g_frag_color.rgb = g_src_color.rgb * g_src_color.a; \n\
00602         g_frag_color.a = g_src_color.a;");
00603       }
00604     else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
00605       {
00606       return std::string(
00607         "l_sum_value = clamp(l_sum_value, 0.0, 1.0); \n\
00608          g_frag_color = vec4(vec3(l_sum_value), 1.0);");
00609       }
00610     else
00611       {
00612       return std::string("");
00613       }
00614   }
00615 
00616   //--------------------------------------------------------------------------
00617   std::string TerminationGlobalsVert(vtkRenderer* vtkNotUsed(ren),
00618                                      vtkVolumeMapper* vtkNotUsed(mapper),
00619                                      vtkVolume* vtkNotUsed(vol))
00620     {
00621     return std::string("");
00622     }
00623 
00624   //--------------------------------------------------------------------------
00625   std::string TerminationGlobalsFrag(vtkRenderer* vtkNotUsed(ren),
00626                                      vtkVolumeMapper* vtkNotUsed(mapper),
00627                                      vtkVolume* vtkNotUsed(vol))
00628     {
00629     return std::string("");
00630     }
00631 
00632   //--------------------------------------------------------------------------
00633   std::string TerminationInit(vtkRenderer* vtkNotUsed(ren),
00634                               vtkVolumeMapper* vtkNotUsed(mapper),
00635                               vtkVolume* vtkNotUsed(vol))
00636     {
00637     return std::string(
00638       "// Minimum texture access coordinate \n\
00639       const vec3 l_tex_min = vec3(0); \n\
00640       \n\
00641       // Maximum texture access coordinate \n\
00642       const vec3 l_tex_max = vec3(1); \n\
00643       \n\
00644       // Flag to indicate if the raymarch loop should terminate \n\
00645       bool stop = false; \n\
00646       \n\
00647       // 2D Texture fragment coordinates [0,1] from fragment coordinates \n\
00648       // the frame buffer texture has the size of the plain buffer but \n\
00649       // we use a fraction of it. The texture coordinates is less than 1 if \n\
00650       // the reduction factor is less than 1. \n\
00651       // Device coordinates are between -1 and 1. We need texture \n\
00652       // coordinates between 0 and 1 the m_depth_sampler buffer has the \n\
00653       // original size buffer. \n\
00654       vec2 m_frag_tex_coord = \n\
00655         (gl_FragCoord.xy - m_window_lower_left_corner) * \n\
00656                                m_inv_window_size; \n\
00657       vec4 l_depth_value = texture2D(m_depth_sampler, m_frag_tex_coord); \n\
00658       float m_terminate_point_max = 0.0; \n\
00659       \n\
00660       // Depth test \n\
00661       if(gl_FragCoord.z >= l_depth_value.x) \n\
00662        { \n\
00663        discard; \n\
00664        } \n\
00665       \n\
00666       // color buffer or max scalar buffer have a reduced size. \n\
00667       m_frag_tex_coord = (gl_FragCoord.xy - m_window_lower_left_corner) * \n\
00668                            m_inv_original_window_size; \n\
00669       \n\
00670       // Compute max number of iterations it will take before we hit \n\
00671       // the termination point \n\
00672       \n\
00673       // Abscissa of the point on the depth buffer along the ray. \n\
00674       // point in texture coordinates \n\
00675       vec4 m_terminate_point; \n\
00676       m_terminate_point.x = \n\
00677         (gl_FragCoord.x - m_window_lower_left_corner.x) * 2.0 * \n\
00678                             m_inv_window_size.x - 1.0; \n\
00679       m_terminate_point.y = \n\
00680         (gl_FragCoord.y - m_window_lower_left_corner.y) * 2.0 * \n\
00681                             m_inv_window_size.y - 1.0; \n\
00682       m_terminate_point.z = (2.0 * l_depth_value.x - (gl_DepthRange.near + \n\
00683                             gl_DepthRange.far)) / gl_DepthRange.diff; \n\
00684       m_terminate_point.w = 1.0; \n\
00685       \n\
00686       // From normalized device coordinates to eye coordinates. \n\
00687       // m_projection_matrix is inversed because of way VT \n\
00688       // From eye coordinates to texture coordinates \n\
00689       m_terminate_point = m_inverse_texture_dataset_matrix * \n\
00690                           m_inverse_volume_matrix * \n\
00691                           m_inverse_modelview_matrix * \n\
00692                           m_inverse_projection_matrix * \n\
00693                           m_terminate_point; \n\
00694       m_terminate_point /= m_terminate_point.w; \n\
00695       \n\
00696       m_terminate_point_max = \n\
00697         length(m_terminate_point.xyz - g_data_pos.xyz) / \n\
00698                               length(g_dir_step); \n\
00699       float m_current_t = 0.0;");
00700     }
00701 
00702   //--------------------------------------------------------------------------
00703   std::string TerminationIncrement(vtkRenderer* vtkNotUsed(ren),
00704                                    vtkVolumeMapper* vtkNotUsed(mapper),
00705                                    vtkVolume* vtkNotUsed(vol))
00706     {
00707     return std::string(
00708       "// The two constants l_tex_min and l_tex_max have a value of \n\
00709       // vec3(-1,-1,-1) and vec3(1,1,1) respectively. To determine if the \n\
00710       // data value is outside the m_volume data, we use the sign function. \n\
00711       // The sign function return -1 if the value is less than 0, 0 if the \n\
00712       // value is equal to 0 and 1 if value is greater than 0. Hence, the \n\
00713       // sign function for the calculation (sign(g_data_pos-l_tex_min) and \n\
00714       // sign (l_tex_max-g_data_pos)) will give us vec3(1,1,1) at the \n\
00715       // possible minimum and maximum position. \n\
00716       // When we do a dot product between two vec3(1,1,1) we get answer 3. \n\
00717       // So to be within the dataset limits, the dot product will return a \n\
00718       // value less than 3. If it is greater than 3, we are already out of \n\
00719       // the m_volume dataset \n\
00720       stop = dot(sign(g_data_pos - l_tex_min), sign(l_tex_max - g_data_pos)) \n\
00721              < 3.0; \n\
00722       \n\
00723       // If the stopping condition is true we brek out of the ray marching \n\
00724       // loop \n\
00725       if (stop) \n\
00726        { \n\
00727        break; \n\
00728        } \n\
00729       // Early ray termination \n\
00730       // if the currently composited colour alpha is already fully saturated \n\
00731       // we terminated the loop or if we have hit an obstacle in the \n\
00732       // direction of they ray (using depth buffer) we terminate as well. \n\
00733       if((g_frag_color.a > (1 - 1/255.0)) ||  \n\
00734           m_current_t >= m_terminate_point_max) \n\
00735         { \n\
00736         break; \n\
00737         } \n\
00738       ++m_current_t;"
00739     );
00740     }
00741 
00742   //--------------------------------------------------------------------------
00743   std::string TerminationExit(vtkRenderer* vtkNotUsed(ren),
00744                               vtkVolumeMapper* vtkNotUsed(mapper),
00745                               vtkVolume* vtkNotUsed(vol))
00746    {
00747     return std::string("");
00748    }
00749 
00750   //--------------------------------------------------------------------------
00751   std::string CroppingGlobalsVert(vtkRenderer* vtkNotUsed(ren),
00752                                   vtkVolumeMapper* vtkNotUsed(mapper),
00753                                   vtkVolume* vtkNotUsed(vol))
00754   {
00755     return std::string("");
00756   }
00757 
00758   //--------------------------------------------------------------------------
00759   std::string CroppingGlobalsFrag(vtkRenderer* vtkNotUsed(ren),
00760                                   vtkVolumeMapper* mapper,
00761                                   vtkVolume* vtkNotUsed(vol))
00762   {
00763     if (!mapper->GetCropping()) {
00764       return std::string("");
00765     }
00766 
00767     return std::string("\n\
00768       uniform float cropping_planes[6]; \n\
00769       uniform int cropping_flags [32]; \n\
00770       // X: axis = 0, Y: axis = 1, Z: axis = 2 \n\
00771       // cp Cropping plane bounds (minX, maxX, minY, maxY, minZ, maxZ) \n\
00772       int computeRegionCoord(float cp[6], vec3 pos, int axis) \n\
00773       { \n\
00774         int cpmin = axis * 2; \n\
00775         int cpmax = cpmin + 1; \n\
00776         \n\
00777         if (pos[axis] < cp[cpmin]) \n\
00778           { \n\
00779           return 1; \n\
00780           } \n\
00781         else if (pos[axis] >= cp[cpmin] && \n\
00782                  pos[axis]  < cp[cpmax]) \n\
00783           { \n\
00784           return 2; \n\
00785           } \n\
00786         else if (pos[axis] >= cp[cpmax]) \n\
00787           { \n\
00788           return 3; \n\
00789           } \n\
00790         return 0; \n\
00791       } \n\
00792       \n\
00793       int computeRegion(float cp[6], vec3 pos) \n\
00794       { \n\
00795         return ( computeRegionCoord(cp, pos, 0) +  \n\
00796                 (computeRegionCoord(cp, pos, 1) - 1) * 3 + \n\
00797                 (computeRegionCoord(cp, pos, 2) - 1) * 9); \n\
00798       }");
00799   }
00800 
00801   //--------------------------------------------------------------------------
00802   std::string CroppingInit(vtkRenderer* vtkNotUsed(ren),
00803                            vtkVolumeMapper* mapper,
00804                            vtkVolume* vtkNotUsed(vol))
00805   {
00806     if (!mapper->GetCropping()) {
00807       return std::string("");
00808     }
00809 
00810     return std::string("\n\
00811       // Convert cropping region to texture space \n\
00812       float cropping_planes_ts[6];\n\
00813       mat4  datasetToTextureMat = m_inverse_texture_dataset_matrix; \n\
00814       vec4 temp = vec4(cropping_planes[0], cropping_planes[1], 0.0, 1.0); \n\
00815       temp = datasetToTextureMat * temp; \n\
00816       if (temp[3] != 0.0) {temp[0] /= temp[3]; temp[1] /= temp[3];} \n\
00817       cropping_planes_ts[0] = temp[0];\n\
00818       cropping_planes_ts[1] = temp[1];\n\
00819       \n\
00820       temp = vec4(cropping_planes[2], cropping_planes[3], 0.0, 1.0); \n\
00821       temp = datasetToTextureMat * temp; \n\
00822       if (temp[3] != 0.0) {temp[0] /= temp[3]; temp[1] /= temp[3];} \n\
00823       cropping_planes_ts[2] = temp[0];\n\
00824       cropping_planes_ts[3] = temp[1];\n\
00825       \n\
00826       temp = vec4(cropping_planes[4], cropping_planes[5], 0.0, 1.0); \n\
00827       temp = datasetToTextureMat * temp; \n\
00828       if (temp[3] != 0.0) {temp[0] /= temp[3]; temp[1] /= temp[3];} \n\
00829       cropping_planes_ts[4] = temp[0];\n\
00830       cropping_planes_ts[5] = temp[1];");
00831   }
00832 
00833   //--------------------------------------------------------------------------
00834   std::string CroppingIncrement(vtkRenderer* vtkNotUsed(ren),
00835                                 vtkVolumeMapper* mapper,
00836                                 vtkVolume* vtkNotUsed(vol))
00837   {
00838     if (!mapper->GetCropping()) {
00839       return std::string("");
00840     }
00841 
00842     return std::string("\n\
00843       // Determine region \n\
00844       int regionNo = computeRegion(cropping_planes_ts, g_data_pos); \n\
00845       \n\
00846       // Do & operation with cropping flags \n\
00847       // Pass the flag that its Ok to sample or not to sample \n\
00848       if (cropping_flags[regionNo] == 0) \n\
00849        { \n\
00850        // Skip this voxel \n\
00851        l_skip = true; \n\
00852        }");
00853   }
00854 
00855   //--------------------------------------------------------------------------
00856   std::string CroppingExit(vtkRenderer* vtkNotUsed(ren),
00857                            vtkVolumeMapper* vtkNotUsed(mapper),
00858                            vtkVolume* vtkNotUsed(vol))
00859   {
00860     return std::string("");
00861   }
00862 
00863   //--------------------------------------------------------------------------
00864   std::string ClippingGlobalsVert(vtkRenderer* vtkNotUsed(ren),
00865                                   vtkVolumeMapper* vtkNotUsed(mapper),
00866                                   vtkVolume* vtkNotUsed(vol))
00867   {
00868     return std::string("");
00869   }
00870 
00871   //--------------------------------------------------------------------------
00872   std::string ClippingGlobalsFrag(vtkRenderer* vtkNotUsed(ren),
00873                                   vtkVolumeMapper* vtkNotUsed(mapper),
00874                                   vtkVolume* vtkNotUsed(vol))
00875   {
00876     return std::string("");
00877   }
00878 
00879   //--------------------------------------------------------------------------
00880   std::string ClippingInit(vtkRenderer* vtkNotUsed(ren),
00881                            vtkVolumeMapper* mapper,
00882                            vtkVolume* vtkNotUsed(vol))
00883   {
00884     if (!mapper->GetClippingPlanes())
00885       {
00886       return std::string("");
00887       }
00888    else
00889       {
00890       return std::string("\n\
00891         float clipping_planes_ts[48];\n\
00892         int clipping_planes_size = int(m_clipping_planes[0]);\n\
00893         \n\
00894         mat4 world_to_texture_mat = m_inverse_texture_dataset_matrix *\n\
00895                                     m_inverse_volume_matrix;\n\
00896         for (int i = 0; i < clipping_planes_size; i = i + 6)\n\
00897           {\n\
00898           vec4 origin = vec4(m_clipping_planes[i + 1],\n\
00899                              m_clipping_planes[i + 2],\n\
00900                              m_clipping_planes[i + 3], 1.0);\n\
00901           vec4 normal = vec4(m_clipping_planes[i + 4],\n\
00902                              m_clipping_planes[i + 5],\n\
00903                              m_clipping_planes[i + 6], 0.0);\n\
00904           \n\
00905           origin = world_to_texture_mat * origin;\n\
00906           normal = world_to_texture_mat * normal;\n\
00907           \n\
00908           if (origin[3] != 0.0)\n\
00909             {\n\
00910             origin[0] = origin[0] / origin[3];\n\
00911             origin[1] = origin[1] / origin[3];\n\
00912             origin[2] = origin[2] / origin[3];\n\
00913             }\n\
00914           if (normal[3] != 0.0)\n\
00915             {\n\
00916             normal[0] = normal[0] / normal[3];\n\
00917             normal[1] = normal[1] / normal[3];\n\
00918             normal[2] = normal[2] / normal[3];\n\
00919             }\n\
00920           \n\
00921           clipping_planes_ts[i]     = origin[0];\n\
00922           clipping_planes_ts[i + 1] = origin[1];\n\
00923           clipping_planes_ts[i + 2] = origin[2];\n\
00924           \n\
00925           clipping_planes_ts[i + 3] = normal[0];\n\
00926           clipping_planes_ts[i + 4] = normal[1];\n\
00927           clipping_planes_ts[i + 5] = normal[2];\n\
00928           }");
00929       }
00930   }
00931 
00932   //--------------------------------------------------------------------------
00933   std::string ClippingIncrement(vtkRenderer* vtkNotUsed(ren),
00934                                 vtkVolumeMapper* mapper,
00935                                 vtkVolume* vtkNotUsed(vol))
00936   {
00937     if (!mapper->GetClippingPlanes())
00938       {
00939       return std::string("");
00940       }
00941     else
00942       {
00943       return std::string("\n\
00944         for (int i = 0; i < (clipping_planes_size) && !l_skip; i = i + 6)\n\
00945          {\n\
00946          if (dot(vec3(g_data_pos - vec3(clipping_planes_ts[i],\n\
00947                                         clipping_planes_ts[i + 1],\n\
00948                                         clipping_planes_ts[i + 2])),\n\
00949              vec3(clipping_planes_ts[i + 3],\n\
00950                   clipping_planes_ts[i + 4],\n\
00951                   clipping_planes_ts[i + 5])) < 0)\n\
00952            {\n\
00953            l_skip = true;\n\
00954            break;\n\
00955            }\n\
00956          }");
00957       }
00958   }
00959 
00960   //--------------------------------------------------------------------------
00961   std::string ClippingExit(vtkRenderer* vtkNotUsed(ren),
00962                            vtkVolumeMapper* vtkNotUsed(mapper),
00963                            vtkVolume* vtkNotUsed(vol))
00964   {
00965     return std::string("");
00966   }
00967 
00968   //--------------------------------------------------------------------------
00969   std::string BinaryMaskGlobalsFrag(vtkRenderer* vtkNotUsed(ren),
00970                                     vtkVolumeMapper* vtkNotUsed(mapper),
00971                                     vtkVolume* vtkNotUsed(vol),
00972                                     vtkImageData* maskInput,
00973                                     vtkVolumeMask* mask,
00974                                     int vtkNotUsed(maskType))
00975   {
00976     if (!mask || !maskInput)
00977       {
00978       return std::string("");
00979       }
00980     else
00981       {
00982       return std::string("uniform sampler3D m_mask;");
00983       }
00984   }
00985 
00986   //--------------------------------------------------------------------------
00987   std::string BinaryMaskIncrement(vtkRenderer* vtkNotUsed(ren),
00988                                   vtkVolumeMapper* vtkNotUsed(mapper),
00989                                   vtkVolume* vtkNotUsed(vol),
00990                                   vtkImageData* maskInput,
00991                                   vtkVolumeMask* mask,
00992                                   int maskType)
00993   {
00994     if (!mask || !maskInput ||
00995         maskType == vtkGPUVolumeRayCastMapper::LabelMapMaskType)
00996       {
00997       return std::string("");
00998       }
00999     else
01000       {
01001       return std::string("\n\
01002         vec4 maskValue = texture3D(m_mask, g_data_pos);\n\
01003         if(maskValue.a <= 0.0)\n\
01004           {\n\
01005           l_skip = true;\n\
01006           }");
01007       }
01008   }
01009 
01010   //--------------------------------------------------------------------------
01011   std::string CompositeMaskGlobalsFrag(vtkRenderer* vtkNotUsed(ren),
01012                                        vtkVolumeMapper* vtkNotUsed(mapper),
01013                                        vtkVolume* vtkNotUsed(vol),
01014                                        vtkImageData* maskInput,
01015                                        vtkVolumeMask* mask,
01016                                        int maskType)
01017   {
01018     if (!mask || !maskInput ||
01019         maskType != vtkGPUVolumeRayCastMapper::LabelMapMaskType)
01020       {
01021       return std::string("");
01022       }
01023     else
01024       {
01025       return std::string("\n\
01026         uniform float m_mask_blendfactor;\n\
01027         uniform sampler1D m_mask_1;\n\
01028         uniform sampler1D m_mask_2;");
01029       }
01030   }
01031 
01032   //--------------------------------------------------------------------------
01033   std::string CompositeMaskIncrement(vtkRenderer* vtkNotUsed(ren),
01034                                      vtkVolumeMapper* vtkNotUsed(mapper),
01035                                      vtkVolume* vtkNotUsed(vol),
01036                                      vtkImageData* maskInput,
01037                                      vtkVolumeMask* mask,
01038                                      int maskType)
01039   {
01040     if (!mask || !maskInput ||
01041         maskType != vtkGPUVolumeRayCastMapper::LabelMapMaskType)
01042       {
01043       return std::string("");
01044       }
01045     else
01046       {
01047       return std::string("\n\
01048         vec4 scalar = texture3D(m_volume, g_data_pos); \n\
01049         if (m_mask_blendfactor == 0.0)\n\
01050           {\n\
01051           g_src_color = computeColor(scalar);\n\
01052           }\n\
01053         else\n\
01054          {\n\
01055          // Get the mask value at this same location\n\
01056          vec4 maskValue = texture3D(m_mask, g_data_pos);\n\
01057          if(maskValue.a == 0.0)\n\
01058            {\n\
01059            g_src_color = computeColor(scalar);\n\
01060            }\n\
01061          else\n\
01062            {\n\
01063            if (maskValue.a == 1.0/255.0)\n\
01064              {\n\
01065              g_src_color = texture1D(m_mask_1, scalar.w);\n\
01066              }\n\
01067            else\n\
01068              {\n\
01069              // maskValue.a == 2.0/255.0\n\
01070              g_src_color = texture1D(m_mask_2, scalar.w);\n\
01071              }\n\
01072            g_src_color.a = 1.0; \n\
01073            if(m_mask_blendfactor < 1.0) \n\
01074              {\n\
01075              g_src_color = (1.0 - m_mask_blendfactor) * computeColor(scalar)\n\
01076                + m_mask_blendfactor * g_src_color;\n\
01077              }\n\
01078            }\n\
01079           g_src_color.a = computeOpacity(scalar); \n\
01080          }");
01081       }
01082   }
01083 }
01084 
01085 #endif // _vtkVolumeShaderComposer_h
01086 // VTK-HeaderTest-Exclude: vtkVolumeShaderComposer.h