VTK
|
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