VTK  9.1.0
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#include <vtkCamera.h>
19#include <vtkImplicitFunction.h>
21#include <vtkRectilinearGrid.h>
22#include <vtkRenderer.h>
23#include <vtkUniformGrid.h>
24#include <vtkVolume.h>
26#include <vtkVolumeMapper.h>
27#include <vtkVolumeProperty.h>
28#include <vtkVolumeTexture.h>
29
30#include <map>
31#include <sstream>
32#include <string>
33
34namespace
35{
36bool HasGradientOpacity(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs)
37{
38 for (auto& item : inputs)
39 {
40 vtkVolumeProperty* volProp = item.second.Volume->GetProperty();
41 const bool gradOp = (volProp->HasGradientOpacity() || volProp->HasLabelGradientOpacity()) &&
42 !volProp->GetDisableGradientOpacity();
43 if (gradOp)
44 return true;
45 }
46 return false;
47}
48
50{
51 for (auto& item : inputs)
52 {
53 vtkVolumeProperty* volProp = item.second.Volume->GetProperty();
54 const bool lighting = volProp->GetShade() == 1;
55 if (lighting)
56 return true;
57 }
58 return false;
59}
60
61bool UseClippedVoxelIntensity(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs)
62{
63 for (auto& item : inputs)
64 {
65 vtkVolumeProperty* volProp = item.second.Volume->GetProperty();
66 const bool useClippedVoxelIntensity = volProp->GetUseClippedVoxelIntensity() == 1;
67 if (useClippedVoxelIntensity)
68 {
69 return true;
70 }
71 }
72 return false;
73}
74
75const std::string ArrayBaseName(const std::string& arrayName)
76{
77 const std::string base = arrayName.substr(0, arrayName.length() - 3);
78 return base;
79}
80}
81
82// NOTE:
83// In this code, we referred to various spaces described below:
84// Object space: Raw coordinates in space defined by volume matrix
85// Dataset space: Raw coordinates
86// Eye space: Coordinates in eye space (as referred in computer graphics)
87
88namespace vtkvolume
89{
90//--------------------------------------------------------------------------
92 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
93{
94 return std::string(
95 " //Transform vertex (data coordinates) to clip coordinates\n"
96 " // p_clip = T_ProjViewModel * T_dataToWorld * p_data\n"
97 " vec4 pos = in_projectionMatrix * in_modelViewMatrix * in_volumeMatrix[0] *\n"
98 " vec4(in_vertexPos.xyz, 1.0);\n"
99 " gl_Position = pos;\n");
100}
101
102//--------------------------------------------------------------------------
104 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
105{
106 return std::string(
107 " // Transform vertex (data coordinates) to texture coordinates.\n"
108 " // p_texture = T_dataToTex * p_data\n"
109 " vec3 uvx = sign(in_cellSpacing[0]) * (in_inverseTextureDatasetMatrix[0] *\n"
110 " vec4(in_vertexPos, 1.0)).xyz;\n"
111 "\n"
112 " // For point dataset, we offset the texture coordinate\n"
113 " // to account for OpenGL treating voxel at the center of the cell.\n"
114 " // Transform cell tex-coordinates to point tex-coordinates (cellToPoint\n"
115 " // is an identity matrix in the case of cell data).\n"
116 " ip_textureCoords = (in_cellToPoint[0] * vec4(uvx, 1.0)).xyz;\n"
117 " ip_inverseTextureDataAdjusted = in_cellToPoint[0] * in_inverseTextureDatasetMatrix[0];\n");
118}
119
120//--------------------------------------------------------------------------
122 vtkVolume* vtkNotUsed(vol), bool multipleInputs)
123{
124 auto gpuMapper = vtkGPUVolumeRayCastMapper::SafeDownCast(mapper);
125 const int numInputs = gpuMapper->GetInputCount();
126
127 std::ostringstream ss;
128 ss << "uniform vec3 in_cellSpacing[" << numInputs
129 << "];\n"
130 "uniform mat4 in_modelViewMatrix;\n"
131 "uniform mat4 in_projectionMatrix;\n";
132
133 const int numTransf = multipleInputs ? numInputs + 1 : 1;
134 ss << "uniform mat4 in_volumeMatrix[" << numTransf
135 << "];\n"
136 "uniform mat4 in_inverseTextureDatasetMatrix["
137 << numTransf
138 << "];\n"
139 "uniform mat4 in_cellToPoint["
140 << numTransf
141 << "];\n"
142 "\n"
143 "//This variable could be 'invariant varying' but it is declared\n"
144 "//as 'varying' to avoid compiler compatibility issues.\n"
145 "out mat4 ip_inverseTextureDataAdjusted;\n";
146
147 return ss.str();
148}
149
150//--------------------------------------------------------------------------
152 vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs, int vtkNotUsed(numberOfLights),
153 int lightingComplexity, int noOfComponents, int independentComponents)
154{
155 const int numInputs = static_cast<int>(inputs.size());
156
157 std::ostringstream toShaderStr;
158 toShaderStr << "uniform sampler3D in_volume[" << numInputs << "];\n";
159
160 toShaderStr << "uniform vec4 in_volume_scale[" << numInputs
161 << "];\n"
162 "uniform vec4 in_volume_bias["
163 << numInputs << "];\n";
164
166 {
167 toShaderStr << "uniform sampler1D in_coordTexs;\n";
168 toShaderStr << "uniform vec3 in_coordTexSizes;\n";
169 toShaderStr << "uniform vec3 in_coordsScale;\n";
170 toShaderStr << "uniform vec3 in_coordsBias;\n";
171 }
172
173 if (mapper->GetInput()->GetPointGhostArray() || mapper->GetInput()->GetCellGhostArray())
174 {
175 toShaderStr << "uniform sampler3D in_blanking;\n";
176 }
177
178 toShaderStr << "uniform int in_noOfComponents;\n"
179 "\n"
180 "uniform sampler2D in_depthSampler;\n"
181 "\n"
182 "// Camera position\n"
183 "uniform vec3 in_cameraPos;\n";
184
186 if (glMapper->GetUseJittering())
187 {
188 toShaderStr << "uniform sampler2D in_noiseSampler;\n";
189 }
190
191 // For multiple inputs (numInputs > 1), an additional transformation is
192 // needed for the bounding-box.
193 const int numTransf = (numInputs > 1) ? numInputs + 1 : 1;
194 toShaderStr << "uniform mat4 in_volumeMatrix[" << numTransf
195 << "];\n"
196 "uniform mat4 in_inverseVolumeMatrix["
197 << numTransf
198 << "];\n"
199 "uniform mat4 in_textureDatasetMatrix["
200 << numTransf
201 << "];\n"
202 "uniform mat4 in_inverseTextureDatasetMatrix["
203 << numTransf
204 << "];\n"
205 "uniform mat4 in_textureToEye["
206 << numTransf
207 << "];\n"
208 "uniform vec3 in_texMin["
209 << numTransf
210 << "];\n"
211 "uniform vec3 in_texMax["
212 << numTransf
213 << "];\n"
214 "uniform mat4 in_cellToPoint["
215 << numTransf << "];\n";
216
217 toShaderStr << "// view and model matrices\n"
218 "uniform mat4 in_projectionMatrix;\n"
219 "uniform mat4 in_inverseProjectionMatrix;\n"
220 "uniform mat4 in_modelViewMatrix;\n"
221 "uniform mat4 in_inverseModelViewMatrix;\n"
222 "in mat4 ip_inverseTextureDataAdjusted;\n"
223 "\n"
224 "// Ray step size\n"
225 "uniform vec3 in_cellStep["
226 << numInputs << "];\n";
227
228 toShaderStr << "uniform vec2 in_scalarsRange[" << numInputs * 4
229 << "];\n"
230 "uniform vec3 in_cellSpacing["
231 << numInputs
232 << "];\n"
233 "\n"
234 "// Sample distance\n"
235 "uniform float in_sampleDistance;\n"
236 "\n"
237 "// Scales\n"
238 "uniform vec2 in_windowLowerLeftCorner;\n"
239 "uniform vec2 in_inverseOriginalWindowSize;\n"
240 "uniform vec2 in_inverseWindowSize;\n"
241 "uniform vec3 in_textureExtentsMax;\n"
242 "uniform vec3 in_textureExtentsMin;\n"
243 "\n"
244 "// Material and lighting\n"
245 "uniform vec3 in_diffuse[4];\n"
246 "uniform vec3 in_ambient[4];\n"
247 "uniform vec3 in_specular[4];\n"
248 "uniform float in_shininess[4];\n"
249 "\n"
250 "// Others\n"
251 "vec3 g_rayJitter = vec3(0.0);\n"
252 "\n"
253 "uniform vec2 in_averageIPRange;\n";
254
255 toShaderStr << "vec4 g_eyePosObjs[" << numInputs << "];\n";
256
257 const bool hasGradientOpacity = HasGradientOpacity(inputs);
258 if (lightingComplexity > 0 || hasGradientOpacity)
259 {
260 toShaderStr << "uniform bool in_twoSidedLighting;\n";
261 }
262
263 if (lightingComplexity == 3)
264 {
265 toShaderStr << "vec4 g_fragWorldPos;\n"
266 "uniform int in_numberOfLights;\n"
267 "uniform vec3 in_lightAmbientColor[6];\n"
268 "uniform vec3 in_lightDiffuseColor[6];\n"
269 "uniform vec3 in_lightSpecularColor[6];\n"
270 "uniform vec3 in_lightDirection[6];\n"
271 "uniform vec3 in_lightPosition[6];\n"
272 "uniform vec3 in_lightAttenuation[6];\n"
273 "uniform float in_lightConeAngle[6];\n"
274 "uniform float in_lightExponent[6];\n"
275 "uniform int in_lightPositional[6];\n";
276 }
277 else if (lightingComplexity == 2)
278 {
279 toShaderStr << "vec4 g_fragWorldPos;\n"
280 "uniform int in_numberOfLights;\n"
281 "uniform vec3 in_lightAmbientColor[6];\n"
282 "uniform vec3 in_lightDiffuseColor[6];\n"
283 "uniform vec3 in_lightSpecularColor[6];\n"
284 "uniform vec3 in_lightDirection[6];\n";
285 }
286 else
287 {
288 toShaderStr << "uniform vec3 in_lightAmbientColor[1];\n"
289 "uniform vec3 in_lightDiffuseColor[1];\n"
290 "uniform vec3 in_lightSpecularColor[1];\n"
291 "vec4 g_lightPosObj["
292 << numInputs
293 << "];\n"
294 "vec3 g_ldir["
295 << numInputs
296 << "];\n"
297 "vec3 g_vdir["
298 << numInputs
299 << "];\n"
300 "vec3 g_h["
301 << numInputs << "];\n";
302 }
303
304 if (noOfComponents > 1 && independentComponents)
305 {
306 toShaderStr << "uniform vec4 in_componentWeight;\n";
307 }
308
310 glMapper->GetUseDepthPass())
311 {
312 toShaderStr << "uniform sampler2D in_depthPassSampler;\n";
313 }
314
316 {
317 toShaderStr << "#if NUMBER_OF_CONTOURS\n"
318 "uniform float in_isosurfacesValues[NUMBER_OF_CONTOURS];\n"
319 "\n"
320 "int findIsoSurfaceIndex(float scalar, float array[NUMBER_OF_CONTOURS+2])\n"
321 "{\n"
322 " int index = NUMBER_OF_CONTOURS >> 1;\n"
323 " while (scalar > array[index]) ++index;\n"
324 " while (scalar < array[index]) --index;\n"
325 " return index;\n"
326 "}\n"
327 "#endif\n";
328 }
329 else if (glMapper->GetBlendMode() == vtkVolumeMapper::SLICE_BLEND)
330 {
331 vtkVolume* vol = inputs.begin()->second.Volume;
332 vtkImplicitFunction* func = vol->GetProperty()->GetSliceFunction();
333
334 if (func && func->IsA("vtkPlane"))
335 {
336 toShaderStr
337 << "uniform vec3 in_slicePlaneOrigin;\n"
338 "uniform vec3 in_slicePlaneNormal;\n"
339 "vec3 g_intersection;\n"
340 "\n"
341 "float intersectRayPlane(vec3 rayOrigin, vec3 rayDir)\n"
342 "{\n"
343 " vec4 planeNormal = in_inverseVolumeMatrix[0] * vec4(in_slicePlaneNormal, 0.0);\n"
344 " float denom = dot(planeNormal.xyz, rayDir);\n"
345 " if (abs(denom) > 1e-6)\n"
346 " {\n"
347 " vec4 planeOrigin = in_inverseVolumeMatrix[0] * vec4(in_slicePlaneOrigin, 1.0);\n"
348 " return dot(planeOrigin.xyz - rayOrigin, planeNormal.xyz) / denom;\n"
349 " }\n"
350 " return -1.0;\n"
351 "}\n";
352 }
353 }
354
355 return toShaderStr.str();
356}
357
358//--------------------------------------------------------------------------
360 vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs, int lightingComplexity)
361{
363 vtkVolume* vol = inputs.begin()->second.Volume;
364 const int numInputs = static_cast<int>(inputs.size());
365
366 std::ostringstream shaderStr;
369 {
370 shaderStr << "\
371 \n //\
372 \n vec2 fragTexCoord2 = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
373 \n in_inverseWindowSize;\
374 \n vec4 depthValue = texture2D(in_depthPassSampler, fragTexCoord2);\
375 \n vec4 rayOrigin = WindowToNDC(gl_FragCoord.x, gl_FragCoord.y, depthValue.x);\
376 \n\
377 \n // From normalized device coordinates to eye coordinates.\
378 \n // in_projectionMatrix is inversed because of way VT\
379 \n // From eye coordinates to texture coordinates\
380 \n rayOrigin = in_inverseTextureDatasetMatrix[0] *\
381 \n in_inverseVolumeMatrix[0] *\
382 \n in_inverseModelViewMatrix *\
383 \n in_inverseProjectionMatrix *\
384 \n rayOrigin;\
385 \n rayOrigin /= rayOrigin.w;\
386 \n g_rayOrigin = rayOrigin.xyz;";
387 }
388 else
389 {
390 shaderStr << "\
391 \n // Get the 3D texture coordinates for lookup into the in_volume dataset\
392 \n g_rayOrigin = ip_textureCoords.xyz;";
393 }
394
395 shaderStr << "\
396 \n\
397 \n // Eye position in dataset space\
398 \n g_eyePosObj = in_inverseVolumeMatrix[0] * vec4(in_cameraPos, 1.0);";
399 for (int i = 0; i < numInputs; ++i)
400 {
401 // In multi-volume case the first volume matrix is of the bounding box
402 shaderStr << "\
403 \n g_eyePosObjs["
404 << i << "] = in_inverseVolumeMatrix[" << (numInputs > 1 ? i + 1 : i)
405 << "] * vec4(in_cameraPos, 1.0);";
406 }
407 shaderStr << "\n\
408 \n // Getting the ray marching direction (in dataset space)\
409 \n vec3 rayDir = computeRayDirection();\
410 \n\
411 \n // 2D Texture fragment coordinates [0,1] from fragment coordinates.\
412 \n // The frame buffer texture has the size of the plain buffer but \
413 \n // we use a fraction of it. The texture coordinate is less than 1 if\
414 \n // the reduction factor is less than 1.\
415 \n // Device coordinates are between -1 and 1. We need texture\
416 \n // coordinates between 0 and 1. The in_depthSampler\
417 \n // buffer has the original size buffer.\
418 \n vec2 fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
419 \n in_inverseWindowSize;\
420 \n\
421 \n // Multiply the raymarching direction with the step size to get the\
422 \n // sub-step size we need to take at each raymarching step\
423 \n g_dirStep = (ip_inverseTextureDataAdjusted *\
424 \n vec4(rayDir, 0.0)).xyz * in_sampleDistance;\
425 \n";
426
428 {
429 // Intersection is computed with g_rayOrigin, so we should not modify it with Slice mode
430 if (glMapper->GetUseJittering())
431 {
432 shaderStr << "\
433 \n float jitterValue = texture2D(in_noiseSampler, gl_FragCoord.xy /\
434 vec2(textureSize(in_noiseSampler, 0))).x;\
435 \n g_rayJitter = g_dirStep * jitterValue;\
436 \n";
437 }
438 else
439 {
440 shaderStr << "\
441 \n g_rayJitter = g_dirStep;\
442 \n";
443 }
444 shaderStr << "\
445 \n g_rayOrigin += g_rayJitter;\
446 \n";
447 }
448
449 shaderStr << "\
450 \n // Flag to determine if voxel should be considered for the rendering\
451 \n g_skip = false;";
452
453 if (vol->GetProperty()->GetShade() && lightingComplexity == 1)
454 {
455 shaderStr << "\
456 \n // Light position in dataset space";
457 for (int i = 0; i < numInputs; ++i)
458 {
459 // In multi-volume case the first volume matrix is of the bounding box
460 shaderStr << "\
461 \n g_lightPosObj["
462 << i << "] = (in_inverseVolumeMatrix[" << (numInputs > 1 ? i + 1 : i) << "] *\
463 \n vec4(in_cameraPos, 1.0));\
464 \n g_ldir["
465 << i << "] = normalize(g_lightPosObj[" << i << "].xyz - ip_vertexPos);\
466 \n g_vdir["
467 << i << "] = normalize(g_eyePosObjs[" << i << "].xyz - ip_vertexPos);\
468 \n g_h["
469 << i << "] = normalize(g_ldir[" << i << "] + g_vdir[" << i << "]);";
470 }
471 }
472
473 return shaderStr.str();
474}
475
476//--------------------------------------------------------------------------
478 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
479{
481
482 std::string str("\
483 \n g_skip = false;");
484
485 // Blanking support
487 bool blankCells = (dataSet->GetCellGhostArray() != nullptr);
488 bool blankPoints = (dataSet->GetPointGhostArray() != nullptr);
489 if (blankPoints || blankCells)
490 {
491 str += std::string("\
492 \n // Check whether the neighboring points/cells are blank.\
493 \n // Note the half cellStep because texels are point centered.\
494 \n vec3 xvec = vec3(in_cellStep[0].x/2.0, 0.0, 0.0);\
495 \n vec3 yvec = vec3(0.0, in_cellStep[0].y/2.0, 0.0);\
496 \n vec3 zvec = vec3(0.0, 0.0, in_cellStep[0].z/2.0);\
497 \n vec3 texPosPVec[3];\
498 \n texPosPVec[0] = g_dataPos + xvec;\
499 \n texPosPVec[1] = g_dataPos + yvec;\
500 \n texPosPVec[2] = g_dataPos + zvec;\
501 \n vec3 texPosNVec[3];\
502 \n texPosNVec[0] = g_dataPos - xvec;\
503 \n texPosNVec[1] = g_dataPos - yvec;\
504 \n texPosNVec[2] = g_dataPos - zvec;\
505 \n vec4 blankValue = texture3D(in_blanking, g_dataPos);\
506 \n vec4 blankValueXP = texture3D(in_blanking, texPosPVec[0]);\
507 \n vec4 blankValueYP = texture3D(in_blanking, texPosPVec[1]);\
508 \n vec4 blankValueZP = texture3D(in_blanking, texPosPVec[2]);\
509 \n vec4 blankValueXN = texture3D(in_blanking, texPosNVec[0]);\
510 \n vec4 blankValueYN = texture3D(in_blanking, texPosNVec[1]);\
511 \n vec4 blankValueZN = texture3D(in_blanking, texPosNVec[2]);\
512 \n vec3 blankValuePx;\
513 \n blankValuePx[0] = blankValueXP.x;\
514 \n blankValuePx[1] = blankValueYP.x;\
515 \n blankValuePx[2] = blankValueZP.x;\
516 \n vec3 blankValuePy;\
517 \n blankValuePy[0] = blankValueXP.y;\
518 \n blankValuePy[1] = blankValueYP.y;\
519 \n blankValuePy[2] = blankValueZP.y;\
520 \n vec3 blankValueNx;\
521 \n blankValueNx[0] = blankValueXN.x;\
522 \n blankValueNx[1] = blankValueYN.x;\
523 \n blankValueNx[2] = blankValueZN.x;\
524 \n vec3 blankValueNy;\
525 \n blankValueNy[0] = blankValueXN.y;\
526 \n blankValueNy[1] = blankValueYN.y;\
527 \n blankValueNy[2] = blankValueZN.y;\
528 \n");
529 if (blankPoints)
530 {
531 str += std::string("\
532 \n // If the current or neighboring points\
533 \n // (that belong to cells that share this texel) are blanked,\
534 \n // skip the texel. In other words, if point 1 were blank,\
535 \n // texels 0, 1 and 2 would have to be skipped.\
536 \n if (blankValue.x > 0.0 ||\
537 \n any(greaterThan(blankValueNx, vec3(0.0))) ||\
538 \n any(greaterThan(blankValuePx, vec3(0.0))))\
539 \n {\
540 \n // skip this texel\
541 \n g_skip = true;\
542 \n }\
543 \n");
544 if (blankCells)
545 {
546 str += std::string("\
547 \n // If the current or previous cells (that share this texel)\
548 \n // are blanked, skip the texel. In other words, if cell 1\
549 \n // is blanked, texels 1 and 2 would have to be skipped.\
550 \n else if (blankValue.y > 0.0 ||\
551 \n any(greaterThan(blankValuePy, vec3(0.0))) ||\
552 \n any(greaterThan(blankValueNy, vec3(0.0))))\
553 \n {\
554 \n // skip this texel\
555 \n g_skip = true;\
556 \n }\
557 \n");
558 }
559 }
560 else if (blankCells)
561 {
562 str += std::string("\
563 \n // If the current or previous cells (that share this texel)\
564 \n // are blanked, skip the texel. In other words, if cell 1\
565 \n // is blanked, texels 1 and 2 would have to be skipped.\
566 \n if (blankValue.x > 0.0 ||\
567 \n any(greaterThan(blankValueNx, vec3(0.0))) ||\
568 \n any(greaterThan(blankValuePx, vec3(0.0))))\
569 \n {\
570 \n // skip this texel\
571 \n g_skip = true;\
572 \n }\
573 \n");
574 }
575 }
576
578 {
579 str += std::string("\
580 \n g_dataPos = g_intersection;\
581 \n");
582 }
583
584 return str;
585}
586
587//--------------------------------------------------------------------------
589 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
590{
591 return std::string();
592}
593
594//--------------------------------------------------------------------------
596 int independentComponents, std::map<int, std::string> gradientTableMap)
597{
598 auto volProperty = vol->GetProperty();
599 std::ostringstream ss;
600 if (volProperty->HasGradientOpacity())
601 {
602 ss << "uniform sampler2D " << ArrayBaseName(gradientTableMap[0]) << "[" << noOfComponents
603 << "];\n";
604 }
605 bool useLabelGradientOpacity =
606 (volProperty->HasLabelGradientOpacity() && (noOfComponents == 1 || !independentComponents));
607 if (useLabelGradientOpacity)
608 {
609 ss << "uniform sampler2D in_labelMapGradientOpacity;\n";
610 }
611
612 std::string shaderStr = ss.str();
613 if (volProperty->HasGradientOpacity() && (noOfComponents == 1 || !independentComponents))
614 {
615 shaderStr += std::string("\
616 \nfloat computeGradientOpacity(vec4 grad)\
617 \n {\
618 \n return texture2D(" +
619 gradientTableMap[0] + ", vec2(grad.w, 0.0)).r;\
620 \n }");
621 }
622 else if (noOfComponents > 1 && independentComponents && volProperty->HasGradientOpacity())
623 {
624 shaderStr += std::string("\
625 \nfloat computeGradientOpacity(vec4 grad, int component)\
626 \n {");
627
628 for (int i = 0; i < noOfComponents; ++i)
629 {
630 std::ostringstream toString;
631 toString << i;
632 shaderStr += std::string("\
633 \n if (component == " +
634 toString.str() + ")");
635
636 shaderStr += std::string("\
637 \n {\
638 \n return texture2D(" +
639 gradientTableMap[i] + ", vec2(grad.w, 0.0)).r;\
640 \n }");
641 }
642
643 shaderStr += std::string("\
644 \n }");
645 }
646
647 if (useLabelGradientOpacity)
648 {
649 shaderStr += std::string("\
650 \nfloat computeGradientOpacityForLabel(vec4 grad, float label)\
651 \n {\
652 \n return texture2D(in_labelMapGradientOpacity, vec2(grad.w, label)).r;\
653 \n }");
654 }
655
656 return shaderStr;
657}
658
659//--------------------------------------------------------------------------
662{
663 const bool hasLighting = HasLighting(inputs);
664 const bool hasGradientOp = HasGradientOpacity(inputs);
665
666 std::string shaderStr;
667 if (hasLighting || hasGradientOp)
668 {
669 shaderStr += std::string(
670 "// c is short for component\n"
671 "vec4 computeGradient(in vec3 texPos, in int c, in sampler3D volume,in int index)\n"
672 "{\n"
673 " // Approximate Nabla(F) derivatives with central differences.\n"
674 " vec3 g1; // F_front\n"
675 " vec3 g2; // F_back\n"
676 " vec3 xvec = vec3(in_cellStep[index].x, 0.0, 0.0);\n"
677 " vec3 yvec = vec3(0.0, in_cellStep[index].y, 0.0);\n"
678 " vec3 zvec = vec3(0.0, 0.0, in_cellStep[index].z);\n"
679 " vec3 texPosPvec[3];\n"
680 " texPosPvec[0] = texPos + xvec;\n"
681 " texPosPvec[1] = texPos + yvec;\n"
682 " texPosPvec[2] = texPos + zvec;\n"
683 " vec3 texPosNvec[3];\n"
684 " texPosNvec[0] = texPos - xvec;\n"
685 " texPosNvec[1] = texPos - yvec;\n"
686 " texPosNvec[2] = texPos - zvec;\n"
687 " g1.x = texture3D(volume, vec3(texPosPvec[0]))[c];\n"
688 " g1.y = texture3D(volume, vec3(texPosPvec[1]))[c];\n"
689 " g1.z = texture3D(volume, vec3(texPosPvec[2]))[c];\n"
690 " g2.x = texture3D(volume, vec3(texPosNvec[0]))[c];\n"
691 " g2.y = texture3D(volume, vec3(texPosNvec[1]))[c];\n"
692 " g2.z = texture3D(volume, vec3(texPosNvec[2]))[c];\n"
693 "\n");
694 if (UseClippedVoxelIntensity(inputs) && mapper->GetClippingPlanes())
695 {
696 shaderStr +=
697 std::string(" vec4 g1ObjDataPos[3], g2ObjDataPos[3];\n"
698 " for (int i = 0; i < 3; ++i)\n"
699 " {\n"
700 " g1ObjDataPos[i] = clip_texToObjMat * vec4(texPosPvec[i], 1.0);\n"
701 " if (g1ObjDataPos[i].w != 0.0)\n"
702 " {\n"
703 " g1ObjDataPos[i] /= g1ObjDataPos[i].w;\n"
704 " }\n"
705 " g2ObjDataPos[i] = clip_texToObjMat * vec4(texPosNvec[i], 1.0);\n"
706 " if (g2ObjDataPos[i].w != 0.0)\n"
707 " {\n"
708 " g2ObjDataPos[i] /= g2ObjDataPos[i].w;\n"
709 " }\n"
710 " }\n"
711 "\n"
712 " for (int i = 0; i < clip_numPlanes && !g_skip; i = i + 6)\n"
713 " {\n"
714 " vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\n"
715 " in_clippingPlanes[i + 2],\n"
716 " in_clippingPlanes[i + 3]);\n"
717 " vec3 planeNormal = normalize(vec3(in_clippingPlanes[i + 4],\n"
718 " in_clippingPlanes[i + 5],\n"
719 " in_clippingPlanes[i + 6]));\n"
720 " for (int j = 0; j < 3; ++j)\n"
721 " {\n"
722 " if (dot(vec3(planeOrigin - g1ObjDataPos[j].xyz), planeNormal) > 0)\n"
723 " {\n"
724 " g1[j] = in_clippedVoxelIntensity;\n"
725 " }\n"
726 " if (dot(vec3(planeOrigin - g2ObjDataPos[j].xyz), planeNormal) > 0)\n"
727 " {\n"
728 " g2[j] = in_clippedVoxelIntensity;\n"
729 " }\n"
730 " }\n"
731 " }\n"
732 "\n");
733 }
734 shaderStr += std::string(" // Apply scale and bias to the fetched values.\n"
735 " g1 = g1 * in_volume_scale[index][c] + in_volume_bias[index][c];\n"
736 " g2 = g2 * in_volume_scale[index][c] + in_volume_bias[index][c];\n"
737 "\n");
738 if (!hasGradientOp)
739 {
740 shaderStr +=
741 std::string(" // Central differences: (F_front - F_back) / 2h\n"
742 " // This version of computeGradient() is only used for lighting\n"
743 " // calculations (only direction matters), hence the difference is\n"
744 " // not scaled by 2h and a dummy gradient mag is returned (-1.).\n"
745 " return vec4((g1 - g2) / in_cellSpacing[index], -1.0);\n"
746 "}\n");
747 }
748 else
749 {
750 shaderStr += std::string(
751 " // Scale values the actual scalar range.\n"
752 " float range = in_scalarsRange[4*index+c][1] - in_scalarsRange[4*index+c][0];\n"
753 " g1 = in_scalarsRange[4*index+c][0] + range * g1;\n"
754 " g2 = in_scalarsRange[4*index+c][0] + range * g2;\n"
755 "\n"
756 " // Central differences: (F_front - F_back) / 2h\n"
757 " g2 = g1 - g2;\n"
758 "\n"
759 " float avgSpacing = (in_cellSpacing[index].x +\n"
760 " in_cellSpacing[index].y + in_cellSpacing[index].z) / 3.0;\n"
761 " vec3 aspect = in_cellSpacing[index] * 2.0 / avgSpacing;\n"
762 " g2 /= aspect;\n"
763 " float grad_mag = length(g2);\n"
764 "\n"
765 " // Handle normalizing with grad_mag == 0.0\n"
766 " g2 = grad_mag > 0.0 ? normalize(g2) : vec3(0.0);\n"
767 "\n"
768 " // Since the actual range of the gradient magnitude is unknown,\n"
769 " // assume it is in the range [0, 0.25 * dataRange].\n"
770 " range = range != 0 ? range : 1.0;\n"
771 " grad_mag = grad_mag / (0.25 * range);\n"
772 " grad_mag = clamp(grad_mag, 0.0, 1.0);\n"
773 "\n"
774 " return vec4(g2.xyz, grad_mag);\n"
775 "}\n");
776 }
777 }
778 else
779 {
780 shaderStr += std::string(
781 "vec4 computeGradient(in vec3 texPos, in int c, in sampler3D volume, in int index)\n"
782 "{\n"
783 " return vec4(0.0);\n"
784 "}\n");
785 }
786
787 return shaderStr;
788}
789
790//--------------------------------------------------------------------------
792 vtkVolume* vol, int noOfComponents, int independentComponents, int vtkNotUsed(numberOfLights),
793 int lightingComplexity)
794{
795 vtkVolumeProperty* volProperty = vol->GetProperty();
796 std::string shaderStr = std::string("\
797 \nvec4 computeLighting(vec4 color, int component, float label)\
798 \n {\
799 \n vec4 finalColor = vec4(0.0);");
800
801 // Shading for composite blending only
802 int const shadeReqd = volProperty->GetShade() &&
806
807 int const transferMode = volProperty->GetTransferFunctionMode();
808
809 if (shadeReqd || volProperty->HasGradientOpacity() || volProperty->HasLabelGradientOpacity())
810 {
811 switch (transferMode)
812 {
814 shaderStr += std::string(
815 " // Compute gradient function only once\n"
816 " vec4 gradient = computeGradient(g_dataPos, component, in_volume[0], 0);\n");
817 break;
819 shaderStr += std::string(" // TransferFunction2D is enabled so the gradient for\n"
820 " // each component has already been cached\n"
821 " vec4 gradient = g_gradients_0[component];\n");
822 break;
823 }
824 }
825
826 if (shadeReqd)
827 {
828 if (lightingComplexity == 1)
829 {
830 shaderStr += std::string("\
831 \n vec3 diffuse = vec3(0.0);\
832 \n vec3 specular = vec3(0.0);\
833 \n vec3 normal = gradient.xyz;\
834 \n float normalLength = length(normal);\
835 \n if (normalLength > 0.0)\
836 \n {\
837 \n normal = normalize(normal);\
838 \n }\
839 \n else\
840 \n {\
841 \n normal = vec3(0.0, 0.0, 0.0);\
842 \n }\
843 \n float nDotL = dot(normal, g_ldir[0]);\
844 \n float nDotH = dot(normal, g_h[0]);\
845 \n if (nDotL < 0.0 && in_twoSidedLighting)\
846 \n {\
847 \n nDotL = -nDotL;\
848 \n }\
849 \n if (nDotH < 0.0 && in_twoSidedLighting)\
850 \n {\
851 \n nDotH = -nDotH;\
852 \n }\
853 \n if (nDotL > 0.0)\
854 \n {\
855 \n diffuse = nDotL * in_diffuse[component] *\
856 \n in_lightDiffuseColor[0] * color.rgb;\
857 \n }\
858 \n specular = pow(nDotH, in_shininess[component]) *\
859 \n in_specular[component] *\
860 \n in_lightSpecularColor[0];\
861 \n // For the headlight, ignore the light's ambient color\
862 \n // for now as it is causing the old mapper tests to fail\
863 \n finalColor.xyz = in_ambient[component] * color.rgb +\
864 \n diffuse + specular;\
865 \n");
866 }
867 else if (lightingComplexity == 2)
868 {
869 shaderStr += std::string("\
870 \n g_fragWorldPos = in_modelViewMatrix * in_volumeMatrix[0] *\
871 \n in_textureDatasetMatrix[0] * vec4(-g_dataPos, 1.0);\
872 \n if (g_fragWorldPos.w != 0.0)\
873 \n {\
874 \n g_fragWorldPos /= g_fragWorldPos.w;\
875 \n }\
876 \n vec3 vdir = normalize(g_fragWorldPos.xyz);\
877 \n vec3 normal = gradient.xyz;\
878 \n vec3 ambient = vec3(0.0);\
879 \n vec3 diffuse = vec3(0.0);\
880 \n vec3 specular = vec3(0.0);\
881 \n float normalLength = length(normal);\
882 \n if (normalLength > 0.0)\
883 \n {\
884 \n normal = normalize((in_textureToEye[0] * vec4(normal, 0.0)).xyz);\
885 \n }\
886 \n else\
887 \n {\
888 \n normal = vec3(0.0, 0.0, 0.0);\
889 \n }\
890 \n for (int lightNum = 0; lightNum < in_numberOfLights; lightNum++)\
891 \n {\
892 \n vec3 ldir = in_lightDirection[lightNum].xyz;\
893 \n vec3 h = normalize(ldir + vdir);\
894 \n float nDotH = dot(normal, h);\
895 \n if (nDotH < 0.0 && in_twoSidedLighting)\
896 \n {\
897 \n nDotH = -nDotH;\
898 \n }\
899 \n float nDotL = dot(normal, ldir);\
900 \n if (nDotL < 0.0 && in_twoSidedLighting)\
901 \n {\
902 \n nDotL = -nDotL;\
903 \n }\
904 \n if (nDotL > 0.0)\
905 \n {\
906 \n diffuse += in_lightDiffuseColor[lightNum] * nDotL;\
907 \n }\
908 \n if (nDotH > 0.0)\
909 \n {\
910 \n specular = in_lightSpecularColor[lightNum] *\
911 \n pow(nDotH, in_shininess[component]);\
912 \n }\
913 \n ambient += in_lightAmbientColor[lightNum];\
914 \n }\
915 \n finalColor.xyz = in_ambient[component] * ambient +\
916 \n in_diffuse[component] * diffuse * color.rgb +\
917 \n in_specular[component] * specular;");
918 }
919 else if (lightingComplexity == 3)
920 {
921 shaderStr += std::string("\
922 \n g_fragWorldPos = in_modelViewMatrix * in_volumeMatrix[0] *\
923 \n in_textureDatasetMatrix[0] * vec4(g_dataPos, 1.0);\
924 \n if (g_fragWorldPos.w != 0.0)\
925 \n {\
926 \n g_fragWorldPos /= g_fragWorldPos.w;\
927 \n }\
928 \n vec3 viewDirection = normalize(-g_fragWorldPos.xyz);\
929 \n vec3 ambient = vec3(0,0,0);\
930 \n vec3 diffuse = vec3(0,0,0);\
931 \n vec3 specular = vec3(0,0,0);\
932 \n vec3 vertLightDirection;\
933 \n vec3 normal = normalize((in_textureToEye[0] * vec4(gradient.xyz, 0.0)).xyz);\
934 \n vec3 lightDir;\
935 \n for (int lightNum = 0; lightNum < in_numberOfLights; lightNum++)\
936 \n {\
937 \n float attenuation = 1.0;\
938 \n // directional\
939 \n lightDir = in_lightDirection[lightNum];\
940 \n if (in_lightPositional[lightNum] == 0)\
941 \n {\
942 \n vertLightDirection = lightDir;\
943 \n }\
944 \n else\
945 \n {\
946 \n vertLightDirection = (g_fragWorldPos.xyz - in_lightPosition[lightNum]);\
947 \n float distance = length(vertLightDirection);\
948 \n vertLightDirection = normalize(vertLightDirection);\
949 \n attenuation = 1.0 /\
950 \n (in_lightAttenuation[lightNum].x\
951 \n + in_lightAttenuation[lightNum].y * distance\
952 \n + in_lightAttenuation[lightNum].z * distance * distance);\
953 \n // per OpenGL standard cone angle is 90 or less for a spot light\
954 \n if (in_lightConeAngle[lightNum] <= 90.0)\
955 \n {\
956 \n float coneDot = dot(vertLightDirection, lightDir);\
957 \n // if inside the cone\
958 \n if (coneDot >= cos(radians(in_lightConeAngle[lightNum])))\
959 \n {\
960 \n attenuation = attenuation * pow(coneDot, in_lightExponent[lightNum]);\
961 \n }\
962 \n else\
963 \n {\
964 \n attenuation = 0.0;\
965 \n }\
966 \n }\
967 \n }\
968 \n // diffuse and specular lighting\
969 \n float nDotL = dot(normal, vertLightDirection);\
970 \n if (nDotL < 0.0 && in_twoSidedLighting)\
971 \n {\
972 \n nDotL = -nDotL;\
973 \n }\
974 \n if (nDotL > 0.0)\
975 \n {\
976 \n float df = max(0.0, attenuation * nDotL);\
977 \n diffuse += (df * in_lightDiffuseColor[lightNum]);\
978 \n }\
979 \n vec3 h = normalize(vertLightDirection + viewDirection);\
980 \n float nDotH = dot(normal, h);\
981 \n if (nDotH < 0.0 && in_twoSidedLighting)\
982 \n {\
983 \n nDotH = -nDotH;\
984 \n }\
985 \n if (nDotH > 0.0)\
986 \n {\
987 \n float sf = attenuation * pow(nDotH, in_shininess[component]);\
988 \n specular += (sf * in_lightSpecularColor[lightNum]);\
989 \n }\
990 \n ambient += in_lightAmbientColor[lightNum];\
991 \n }\
992 \n finalColor.xyz = in_ambient[component] * ambient +\
993 \n in_diffuse[component] * diffuse * color.rgb +\
994 \n in_specular[component] * specular;\
995 ");
996 }
997 }
998 else
999 {
1000 shaderStr += std::string("\n finalColor = vec4(color.rgb, 0.0);");
1001 }
1002
1003 auto glMapper = vtkOpenGLGPUVolumeRayCastMapper::SafeDownCast(mapper);
1004 // For 1D transfers only (2D transfer functions hold scalar and
1005 // gradient-magnitude opacities combined in the same table).
1006 // For multiple inputs, a different computeGradientOpacity() signature
1007 // is defined.
1008 if (transferMode == vtkVolumeProperty::TF_1D && glMapper->GetInputCount() == 1)
1009 {
1010 if (noOfComponents == 1 || !independentComponents)
1011 {
1012 if (volProperty->HasGradientOpacity())
1013 {
1014 shaderStr += std::string("\
1015 \n if (gradient.w >= 0.0 && label == 0.0)\
1016 \n {\
1017 \n color.a *= computeGradientOpacity(gradient);\
1018 \n }");
1019 }
1020 if (volProperty->HasLabelGradientOpacity())
1021 {
1022 shaderStr += std::string("\
1023 \n if (gradient.w >= 0.0 && label > 0.0)\
1024 \n {\
1025 \n color.a *= computeGradientOpacityForLabel(gradient, label);\
1026 \n }");
1027 }
1028 }
1029 else if (noOfComponents > 1 && independentComponents && volProperty->HasGradientOpacity())
1030 {
1031 shaderStr += std::string("\
1032 \n if (gradient.w >= 0.0)\
1033 \n {\
1034 \n for (int i = 0; i < in_noOfComponents; ++i)\
1035 \n {\
1036 \n color.a = color.a *\
1037 \n computeGradientOpacity(gradient, i) * in_componentWeight[i];\
1038 \n }\
1039 \n }");
1040 }
1041 }
1042
1043 shaderStr += std::string("\
1044 \n finalColor.a = color.a;\
1045 \n return finalColor;\
1046 \n }");
1047
1048 return shaderStr;
1049}
1050
1051//--------------------------------------------------------------------------
1053 vtkVolume* vol, int noOfComponents, int independentComponents, int vtkNotUsed(numberOfLights),
1054 int lightingComplexity)
1055{
1056 vtkVolumeProperty* volProperty = vol->GetProperty();
1057
1058 std::string shaderStr = std::string();
1059
1060 // if no gradient TF is needed, don't add it into the function signature
1061 if (volProperty->HasGradientOpacity())
1062 {
1063 shaderStr += std::string("\
1064 \nvec4 computeLighting(vec3 texPos, vec4 color, const in sampler2D gradientTF, const in sampler3D volume, const int volIdx, int component)\
1065 \n {\
1066 \n vec4 finalColor = vec4(0.0);");
1067 }
1068 else
1069 {
1070 shaderStr += std::string("\
1071 \nvec4 computeLighting(vec3 texPos, vec4 color, const in sampler3D volume, const int volIdx, int component)\
1072 \n {\
1073 \n vec4 finalColor = vec4(0.0);");
1074 }
1075
1076 // Shading for composite blending only
1077 int const shadeReqd = volProperty->GetShade() &&
1080
1081 int const transferMode = volProperty->GetTransferFunctionMode();
1082
1083 if ((shadeReqd || volProperty->HasGradientOpacity()) && transferMode == vtkVolumeProperty::TF_1D)
1084 {
1085 shaderStr +=
1086 std::string(" // Compute gradient function only once\n"
1087 " vec4 gradient = computeGradient(texPos, component, volume, volIdx);\n");
1088 }
1089
1090 if (shadeReqd && lightingComplexity == 1)
1091 {
1092 shaderStr += std::string("\
1093 \n vec3 diffuse = vec3(0.0);\
1094 \n vec3 specular = vec3(0.0);\
1095 \n vec3 normal = gradient.xyz;\
1096 \n float normalLength = length(normal);\
1097 \n if (normalLength > 0.0)\
1098 \n {\
1099 \n normal = normalize(normal);\
1100 \n }\
1101 \n else\
1102 \n {\
1103 \n normal = vec3(0.0, 0.0, 0.0);\
1104 \n }\
1105 \n float nDotL = dot(normal, g_ldir[volIdx]);\
1106 \n float nDotH = dot(normal, g_h[volIdx]);\
1107 \n if (nDotL < 0.0 && in_twoSidedLighting)\
1108 \n {\
1109 \n nDotL = -nDotL;\
1110 \n }\
1111 \n if (nDotH < 0.0 && in_twoSidedLighting)\
1112 \n {\
1113 \n nDotH = -nDotH;\
1114 \n }\
1115 \n if (nDotL > 0.0)\
1116 \n {\
1117 \n diffuse = nDotL * in_diffuse[component] *\
1118 \n in_lightDiffuseColor[0] * color.rgb;\
1119 \n }\
1120 \n specular = pow(nDotH, in_shininess[component]) *\
1121 \n in_specular[component] *\
1122 \n in_lightSpecularColor[0];\
1123 \n // For the headlight, ignore the light's ambient color\
1124 \n // for now as it is causing the old mapper tests to fail\
1125 \n finalColor.xyz = in_ambient[component] * color.rgb +\
1126 \n diffuse + specular;\
1127 \n");
1128 }
1129 else
1130 {
1131 shaderStr += std::string("\n finalColor = vec4(color.rgb, 0.0);");
1132 }
1133
1134 // For 1D transfers only (2D transfer functions hold scalar and
1135 // gradient-magnitude opacities combined in the same table).
1136 if (transferMode == vtkVolumeProperty::TF_1D)
1137 {
1138 if (volProperty->HasGradientOpacity() && (noOfComponents == 1 || !independentComponents))
1139 {
1140 shaderStr += std::string("\
1141 \n if (gradient.w >= 0.0)\
1142 \n {\
1143 \n color.a = color.a *\
1144 \n computeGradientOpacity(gradient, gradientTF);\
1145 \n }");
1146 }
1147 }
1148
1149 shaderStr += std::string("\
1150 \n finalColor.a = color.a;\
1151 \n return clamp(finalColor, 0.0, 1.0);\
1152 \n }");
1153
1154 return shaderStr;
1155}
1156
1157//--------------------------------------------------------------------------
1159 vtkVolume* vtkNotUsed(vol), int vtkNotUsed(noOfComponents))
1160{
1162 {
1163 return std::string("\
1164 \nvec3 computeRayDirection()\
1165 \n {\
1166 \n return normalize(ip_vertexPos.xyz - g_eyePosObj.xyz);\
1167 \n }");
1168 }
1169 else
1170 {
1171 return std::string("\
1172 \nuniform vec3 in_projectionDirection;\
1173 \nvec3 computeRayDirection()\
1174 \n {\
1175 \n return normalize((in_inverseVolumeMatrix[0] *\
1176 \n vec4(in_projectionDirection, 0.0)).xyz);\
1177 \n }");
1178 }
1179}
1180
1181//--------------------------------------------------------------------------
1183 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), int noOfComponents,
1184 int independentComponents, std::map<int, std::string> colorTableMap)
1185{
1186 std::ostringstream ss;
1187 ss << "uniform sampler2D " << ArrayBaseName(colorTableMap[0]) << "[" << noOfComponents << "];\n";
1188
1189 std::string shaderStr = ss.str();
1190 if (noOfComponents == 1)
1191 {
1192 shaderStr += std::string("\
1193 \nvec4 computeColor(vec4 scalar, float opacity)\
1194 \n {\
1195 \n return clamp(computeLighting(vec4(texture2D(" +
1196 colorTableMap[0] + ",\
1197 \n vec2(scalar.w, 0.0)).xyz, opacity), 0, 0.0), 0.0, 1.0);\
1198 \n }");
1199 return shaderStr;
1200 }
1201 else if (noOfComponents > 1 && independentComponents)
1202 {
1203 std::ostringstream toString;
1204
1205 shaderStr += std::string("\
1206 \nvec4 computeColor(vec4 scalar, float opacity, int component)\
1207 \n {");
1208
1209 for (int i = 0; i < noOfComponents; ++i)
1210 {
1211 toString << i;
1212 shaderStr += std::string("\
1213 \n if (component == " +
1214 toString.str() + ")");
1215
1216 shaderStr += std::string("\
1217 \n {\
1218 \n return clamp(computeLighting(vec4(texture2D(\
1219 \n " +
1220 colorTableMap[i]);
1221 shaderStr += std::string(", vec2(\
1222 \n scalar[" +
1223 toString.str() + "],0.0)).xyz,\
1224 \n opacity)," +
1225 toString.str() + ", 0.0), 0.0, 1.0);\
1226 \n }");
1227
1228 // Reset
1229 toString.str("");
1230 toString.clear();
1231 }
1232
1233 shaderStr += std::string("\n }");
1234 return shaderStr;
1235 }
1236 else if (noOfComponents == 2 && !independentComponents)
1237 {
1238 shaderStr += std::string("\
1239 \nvec4 computeColor(vec4 scalar, float opacity)\
1240 \n {\
1241 \n return clamp(computeLighting(vec4(texture2D(" +
1242 colorTableMap[0] + ",\
1243 \n vec2(scalar.x, 0.0)).xyz,\
1244 \n opacity), 0, 0.0), 0.0, 1.0);\
1245 \n }");
1246 return shaderStr;
1247 }
1248 else
1249 {
1250 shaderStr += std::string("\
1251 \nvec4 computeColor(vec4 scalar, float opacity)\
1252 \n {\
1253 \n return clamp(computeLighting(vec4(scalar.xyz, opacity), 0, 0.0), 0.0, 1.0);\
1254 \n }");
1255 return shaderStr;
1256 }
1257}
1258
1259//--------------------------------------------------------------------------
1261 vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs, bool useGradientTF)
1262{
1263 std::ostringstream ss;
1264 int i = 0;
1265 int lastComponentMode = vtkVolumeInputHelper::INVALID;
1266 std::map<int, std::string> lastColorTableMap;
1267 for (auto& item : inputs)
1268 {
1269 auto prop = item.second.Volume->GetProperty();
1270 if (prop->GetTransferFunctionMode() != vtkVolumeProperty::TF_1D)
1271 continue;
1272
1273 auto& map = item.second.RGBTablesMap;
1274 const auto numComp = map.size();
1275 ss << "uniform sampler2D " << ArrayBaseName(map[0]) << "[" << numComp << "];\n";
1276
1277 lastComponentMode = item.second.ComponentMode;
1278 lastColorTableMap = map;
1279 i++;
1280 }
1281
1282 if (lastComponentMode == vtkVolumeInputHelper::LA)
1283 {
1284 ss << "vec4 computeColor(vec4 scalar, const in sampler2D colorTF)\
1285 \n {\
1286 \n return clamp(computeLighting(vec4(texture2D(colorTF,\
1287 \n vec2(scalar.w, 0.0)).xyz, opacity), 0), 0.0, 1.0);\
1288 \n }\n";
1289 }
1290 else
1291 {
1292 if (useGradientTF)
1293 {
1294 ss
1295 << "vec4 computeColor(vec3 texPos, vec4 scalar, float opacity, const in sampler2D colorTF, "
1296 "const in sampler2D gradientTF, const in sampler3D volume, const int volIdx)\n"
1297 "{\n"
1298 " return clamp(computeLighting(texPos, vec4(texture2D(colorTF,\n"
1299 " vec2(scalar.w, 0.0)).xyz, opacity), gradientTF, volume, "
1300 "volIdx, 0), 0.0, 1.0);\n"
1301 "}\n";
1302 }
1303 else
1304 {
1305 ss
1306 << "vec4 computeColor(vec3 texPos, vec4 scalar, float opacity, const in sampler2D colorTF, "
1307 "const in sampler3D volume, const int volIdx)\n"
1308 "{\n"
1309 " return clamp(computeLighting(texPos, vec4(texture2D(colorTF,\n"
1310 " vec2(scalar.w, 0.0)).xyz, opacity), volume, "
1311 "volIdx, 0), 0.0, 1.0);\n"
1312 "}\n";
1313 }
1314 }
1315
1316 return ss.str();
1317}
1318
1319//--------------------------------------------------------------------------
1321{
1322 std::ostringstream ss;
1323 int i = 0;
1324 for (auto& item : inputs)
1325 {
1326 auto prop = item.second.Volume->GetProperty();
1327 if (prop->GetTransferFunctionMode() != vtkVolumeProperty::TF_1D)
1328 continue;
1329
1330 auto& map = item.second.OpacityTablesMap;
1331 const auto numComp = map.size();
1332 ss << "uniform sampler2D " << ArrayBaseName(map[0]) << "[" << numComp << "];\n";
1333 i++;
1334 }
1335
1336 ss << "float computeOpacity(vec4 scalar, const in sampler2D opacityTF)\n"
1337 "{\n"
1338 " return texture2D(opacityTF, vec2(scalar.w, 0)).r;\n"
1339 "}\n";
1340 return ss.str();
1341}
1342
1343//--------------------------------------------------------------------------
1346{
1347 std::ostringstream ss;
1348
1349 int i = 0;
1350 for (auto& item : inputs)
1351 {
1352 auto prop = item.second.Volume->GetProperty();
1353 if (prop->GetTransferFunctionMode() != vtkVolumeProperty::TF_1D || !prop->HasGradientOpacity())
1354 continue;
1355
1356 auto& map = item.second.GradientOpacityTablesMap;
1357 const auto numComp = map.size();
1358 ss << "uniform sampler2D " << ArrayBaseName(map[0]) << "[" << numComp << "];\n";
1359 i++;
1360 }
1361
1362 ss << "float computeGradientOpacity(vec4 grad, const in sampler2D gradientTF)\n"
1363 "{\n"
1364 " return texture2D(gradientTF, vec2(grad.w, 0.0)).r;\n"
1365 "}\n";
1366 return ss.str();
1367}
1368
1369//--------------------------------------------------------------------------
1371 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), int noOfComponents,
1372 int independentComponents, std::map<int, std::string> opacityTableMap)
1373{
1374 std::ostringstream ss;
1375 ss << "uniform sampler2D " << ArrayBaseName(opacityTableMap[0]) << "[" << noOfComponents
1376 << "];\n";
1377
1378 std::string shaderStr = ss.str();
1379 if (noOfComponents > 1 && independentComponents)
1380 {
1381 shaderStr += std::string("\
1382 \nfloat computeOpacity(vec4 scalar, int component)\
1383 \n{");
1384
1385 for (int i = 0; i < noOfComponents; ++i)
1386 {
1387 std::ostringstream toString;
1388 toString << i;
1389 shaderStr += std::string("\
1390 \n if (component == " +
1391 toString.str() + ")");
1392
1393 shaderStr += std::string("\
1394 \n {\
1395 \n return texture2D(" +
1396 opacityTableMap[i]);
1397
1398 shaderStr += std::string(",vec2(scalar[" + toString.str() + "], 0)).r;\
1399 \n }");
1400 }
1401
1402 shaderStr += std::string("\n}");
1403 return shaderStr;
1404 }
1405 else if (noOfComponents == 2 && !independentComponents)
1406 {
1407 shaderStr += std::string("\
1408 \nfloat computeOpacity(vec4 scalar)\
1409 \n{\
1410 \n return texture2D(" +
1411 opacityTableMap[0] + ", vec2(scalar.y, 0)).r;\
1412 \n}");
1413 return shaderStr;
1414 }
1415 else
1416 {
1417 shaderStr += std::string("\
1418 \nfloat computeOpacity(vec4 scalar)\
1419 \n{\
1420 \n return texture2D(" +
1421 opacityTableMap[0] + ", vec2(scalar.w, 0)).r;\
1422 \n}");
1423 return shaderStr;
1424 }
1425}
1426
1427//--------------------------------------------------------------------------
1429 int vtkNotUsed(independentComponents), std::map<int, std::string> colorTableMap)
1430{
1431 if (noOfComponents == 1)
1432 {
1433 // Single component
1434 return std::string(
1435 "vec4 computeColor(vec4 scalar, float opacity)\n"
1436 "{\n"
1437 " vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
1438 " yscalar.r = yscalar.r * in_transfer2DYAxis_scale.r + in_transfer2DYAxis_bias.r;\n"
1439 " yscalar = vec4(yscalar.r);\n"
1440 " vec4 color = texture2D(" +
1441 colorTableMap[0] +
1442 ",\n"
1443 " vec2(scalar.w, yscalar.w));\n"
1444 " return computeLighting(color, 0, 0);\n"
1445 "}\n");
1446 }
1447 return std::string("vec4 computeColor(vec4 scalar, float opacity)\n"
1448 "{\n"
1449 " return vec4(0, 0, 0, 0)\n"
1450 "}\n");
1451}
1452
1453//--------------------------------------------------------------------------
1455 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), int noOfComponents,
1456 int independentComponents, std::map<int, std::string> colorTableMap, int useGradient)
1457{
1458 if (!useGradient)
1459 {
1460 return ComputeColor2DYAxisDeclaration(noOfComponents, independentComponents, colorTableMap);
1461 }
1462 if (noOfComponents == 1)
1463 {
1464 // Single component
1465 return std::string("vec4 computeColor(vec4 scalar, float opacity)\n"
1466 "{\n"
1467 " vec4 color = texture2D(" +
1468 colorTableMap[0] +
1469 ",\n"
1470 " vec2(scalar.w, g_gradients_0[0].w));\n"
1471 " return computeLighting(color, 0, 0);\n"
1472 "}\n");
1473 }
1474 else if (noOfComponents > 1 && independentComponents)
1475 {
1476 // Multiple independent components
1477 std::string shaderStr;
1478 shaderStr += std::string("vec4 computeColor(vec4 scalar, float opacity, int component)\n"
1479 "{\n");
1480
1481 for (int i = 0; i < noOfComponents; ++i)
1482 {
1483 std::ostringstream toString;
1484 toString << i;
1485 std::string const num = toString.str();
1486 shaderStr += std::string(" if (component == " + num +
1487 ")\n"
1488 " {\n"
1489 " vec4 color = texture2D(" +
1490 colorTableMap[i] +
1491 ",\n"
1492 " vec2(scalar[" +
1493 num + "], g_gradients_0[" + num +
1494 "].w));\n"
1495 " return computeLighting(color, " +
1496 num +
1497 ", 0.0);\n"
1498 " }\n");
1499 }
1500 shaderStr += std::string("}\n");
1501
1502 return shaderStr;
1503 }
1504 else if (noOfComponents == 2 && !independentComponents)
1505 {
1506 // Dependent components (Luminance/ Opacity)
1507 return std::string("vec4 computeColor(vec4 scalar, float opacity)\n"
1508 "{\n"
1509 " vec4 color = texture2D(" +
1510 colorTableMap[0] +
1511 ",\n"
1512 " vec2(scalar.x, g_gradients_0[0].w));\n"
1513 " return computeLighting(color, 0, 0.0);\n"
1514 "}\n");
1515 }
1516 else
1517 {
1518 return std::string("vec4 computeColor(vec4 scalar, float opacity)\n"
1519 "{\n"
1520 " return computeLighting(vec4(scalar.xyz, opacity), 0, 0.0);\n"
1521 "}\n");
1522 }
1523}
1524
1525//--------------------------------------------------------------------------
1527{
1528 std::ostringstream ss;
1529 int i = 0;
1530 for (auto& item : inputs)
1531 {
1532 auto prop = item.second.Volume->GetProperty();
1533 if (prop->GetTransferFunctionMode() != vtkVolumeProperty::TF_2D)
1534 continue;
1535
1536 auto& map = item.second.TransferFunctions2DMap;
1537 const auto numComp = map.size();
1538 ss << "uniform sampler2D " << ArrayBaseName(map[0]) << "[" << numComp << "];\n";
1539 i++;
1540 }
1541
1542 std::string result = ss.str() +
1543 std::string("uniform sampler3D in_transfer2DYAxis;\n"
1544 "uniform vec4 in_transfer2DYAxis_scale;\n"
1545 "uniform vec4 in_transfer2DYAxis_bias;\n");
1546
1547 return result;
1548}
1549
1550//--------------------------------------------------------------------------
1552 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), int noOfComponents,
1553 int independentComponents, std::map<int, std::string> opacityTableMap, int useGradient)
1554{
1555 std::ostringstream toString;
1556 if (noOfComponents > 1 && independentComponents)
1557 {
1558 // Multiple independent components
1559 toString << "float computeOpacity(vec4 scalar, int component)\n"
1560 "{\n";
1561 if (!useGradient)
1562 {
1563 toString
1564 << "vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
1565 "for (int i = 0; i < 4; ++i)\n"
1566 "{\n"
1567 " yscalar[i] = yscalar[i] * in_transfer2DYAxis_scale[i] + in_transfer2DYAxis_bias[i];\n"
1568 "}\n";
1569 if (noOfComponents == 1)
1570 {
1571 toString << "yscalar = vec4(yscalar.r);\n";
1572 }
1573 }
1574
1575 for (int i = 0; i < noOfComponents; ++i)
1576 {
1577 if (useGradient)
1578 {
1579 toString << " if (component == " << i
1580 << ")\n"
1581 " {\n"
1582 " return texture2D("
1583 << opacityTableMap[i]
1584 << ",\n"
1585 " vec2(scalar["
1586 << i << "], g_gradients_0[" << i
1587 << "].w)).a;\n"
1588 " }\n";
1589 }
1590 else
1591 {
1592 toString << " if (component == " << i
1593 << ")\n"
1594 " {\n"
1595 " return texture2D("
1596 << opacityTableMap[i]
1597 << ",\n"
1598 " vec2(scalar["
1599 << i << "], yscalar[" << i
1600 << "])).a;\n"
1601 " }\n";
1602 }
1603 }
1604
1605 toString << "}\n";
1606 }
1607
1608 else if (noOfComponents == 2 && !independentComponents)
1609 {
1610 if (useGradient)
1611 {
1612 // Dependent components (Luminance/ Opacity)
1613 toString << "float computeOpacity(vec4 scalar)\n"
1614 "{\n"
1615 " return texture2D(" +
1616 opacityTableMap[0] +
1617 ",\n"
1618 " vec2(scalar.y, g_gradients_0[0].w)).a;\n"
1619 "}\n";
1620 }
1621 else
1622 {
1623 // Dependent components (Luminance/ Opacity)
1624 toString << "float computeOpacity(vec4 scalar)\n"
1625 "{\n"
1626 " return texture2D(" +
1627 opacityTableMap[0] +
1628 ",\n"
1629 " vec2(scalar.y, yscalar.y)).a;\n"
1630 "}\n";
1631 }
1632 }
1633
1634 else
1635 {
1636 if (useGradient)
1637 {
1638 // Dependent compoennts (RGBA) || Single component
1639 toString << "float computeOpacity(vec4 scalar)\n"
1640 "{\n"
1641 " return texture2D(" +
1642 opacityTableMap[0] +
1643 ",\n"
1644 " vec2(scalar.a, g_gradients_0[0].w)).a;\n"
1645 "}\n";
1646 }
1647 else
1648 {
1649 // Dependent compoennts (RGBA) || Single component
1650 toString
1651 << "float computeOpacity(vec4 scalar)\n"
1652 "{\n"
1653 " vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
1654 " yscalar.r = yscalar.r * in_transfer2DYAxis_scale.r + in_transfer2DYAxis_bias.r;\n"
1655 " yscalar = vec4(yscalar.r);\n"
1656 " return texture2D(" +
1657 opacityTableMap[0] +
1658 ",\n"
1659 " vec2(scalar.a, yscalar.w)).a;\n"
1660 "}\n";
1661 }
1662 }
1663 return toString.str();
1664}
1665
1666//--------------------------------------------------------------------------
1668 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
1669{
1670 return std::string();
1671}
1672
1673//--------------------------------------------------------------------------
1675 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
1676{
1678 {
1679 return std::string("\
1680 \n bool l_firstValue;\
1681 \n vec4 l_maxValue;");
1682 }
1684 {
1685 return std::string("\
1686 \n bool l_firstValue;\
1687 \n vec4 l_minValue;");
1688 }
1690 {
1691 return std::string("\
1692 \n uvec4 l_numSamples;\
1693 \n vec4 l_avgValue;");
1694 }
1695 else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
1696 {
1697 return std::string("\
1698 \n vec4 l_sumValue;");
1699 }
1700 else if (mapper->GetBlendMode() == vtkVolumeMapper::ISOSURFACE_BLEND)
1701 {
1702 return std::string("\
1703 \n int l_initialIndex = 0;\
1704 \n float l_normValues[NUMBER_OF_CONTOURS + 2];");
1705 }
1706 else
1707 {
1708 return std::string();
1709 }
1710}
1711
1712//--------------------------------------------------------------------------
1714 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
1715{
1717 {
1718 return std::string("\
1719 \n // We get data between 0.0 - 1.0 range\
1720 \n l_firstValue = true;\
1721 \n l_maxValue = vec4(0.0);");
1722 }
1724 {
1725 return std::string("\
1726 \n //We get data between 0.0 - 1.0 range\
1727 \n l_firstValue = true;\
1728 \n l_minValue = vec4(1.0);");
1729 }
1731 {
1732 return std::string("\
1733 \n //We get data between 0.0 - 1.0 range\
1734 \n l_avgValue = vec4(0.0);\
1735 \n // Keep track of number of samples\
1736 \n l_numSamples = uvec4(0);");
1737 }
1738 else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
1739 {
1740 return std::string("\
1741 \n //We get data between 0.0 - 1.0 range\
1742 \n l_sumValue = vec4(0.0);");
1743 }
1744 else if (mapper->GetBlendMode() == vtkVolumeMapper::ISOSURFACE_BLEND)
1745 {
1746 return std::string("\
1747 \n#if NUMBER_OF_CONTOURS\
1748 \n l_normValues[0] = -1e20; //-infinity\
1749 \n l_normValues[NUMBER_OF_CONTOURS+1] = +1e20; //+infinity\
1750 \n for (int i = 0; i < NUMBER_OF_CONTOURS; i++)\
1751 \n {\
1752 \n l_normValues[i+1] = (in_isosurfacesValues[i] - in_scalarsRange[0].x) / \
1753 \n (in_scalarsRange[0].y - in_scalarsRange[0].x);\
1754 \n }\
1755 \n#endif\
1756 ");
1757 }
1758 else
1759 {
1760 return std::string();
1761 }
1762}
1763
1764//--------------------------------------------------------------------------
1765std::string GradientCacheDec(vtkRenderer* vtkNotUsed(ren), vtkVolume* vtkNotUsed(vol),
1766 vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs, int independentComponents = 0)
1767{
1768 const int numInputs = static_cast<int>(inputs.size());
1769 const int comp = numInputs == 1 ?
1770 // Dependent components use a single opacity lut.
1771 (!independentComponents ? 1 : numInputs)
1772 :
1773 // Independent components not supported with multiple-inputs
1774 1;
1775
1776 std::ostringstream toShader;
1777 for (const auto& item : inputs)
1778 {
1779 auto& input = item.second;
1780 if (input.Volume->GetProperty()->HasGradientOpacity())
1781 {
1782 toShader << "vec4 " << input.GradientCacheName << "[" << comp << "];\n";
1783 }
1784 }
1785
1786 return toShader.str();
1787}
1788
1789//--------------------------------------------------------------------------
1791 int noOfComponents = 1, int independentComponents = 0)
1792{
1793 std::ostringstream shader;
1794 if (independentComponents)
1795 {
1796 if (noOfComponents == 1)
1797 {
1798 shader << "g_gradients_0[0] = computeGradient(g_dataPos, 0, in_volume[0], 0);\n";
1799 }
1800 else
1801 {
1802 // Multiple components
1803 shader << "for (int comp = 0; comp < in_noOfComponents; comp++)\n"
1804 "{\n"
1805 " g_gradients_0[comp] = computeGradient(g_dataPos, comp, in_volume[0], 0);\n"
1806 "}\n";
1807 }
1808 }
1809 else
1810 {
1811 shader << "g_gradients_0[0] = computeGradient(g_dataPos, 0, in_volume[0], 0);\n";
1812 }
1813
1814 return shader.str();
1815}
1816
1817//--------------------------------------------------------------------------
1820{
1821 std::ostringstream toShaderStr;
1822 toShaderStr << " if (!g_skip)\n"
1823 " {\n"
1824 " vec3 texPos;\n";
1825
1826 switch (mapper->GetBlendMode())
1827 {
1829 default:
1830 {
1831 int i = 0;
1832 for (auto& item : inputs)
1833 {
1834 auto& input = item.second;
1835 auto property = input.Volume->GetProperty();
1836 // Transformation index. Index 0 refers to the global bounding-box.
1837 const auto idx = i + 1;
1838 toShaderStr <<
1839 // From global texture coordinates (bbox) to volume_i texture coords.
1840 // texPos = T * g_dataPos
1841 // T = T_dataToTex1 * T_worldToData * T_bboxTexToWorld;
1842 " texPos = (in_cellToPoint[" << idx << "] * in_inverseTextureDatasetMatrix[" << idx
1843 << "] * in_inverseVolumeMatrix[" << idx
1844 << "] *\n"
1845 " in_volumeMatrix[0] * in_textureDatasetMatrix[0] * "
1846 "vec4(g_dataPos.xyz, 1.0)).xyz;\n"
1847 " if ((all(lessThanEqual(texPos, vec3(1.0))) &&\n"
1848 " all(greaterThanEqual(texPos, vec3(0.0)))))\n"
1849 " {\n"
1850 " vec4 scalar = texture3D(in_volume["
1851 << i
1852 << "], texPos);\n"
1853 " scalar = scalar * in_volume_scale["
1854 << i << "] + in_volume_bias[" << i
1855 << "];\n"
1856 " scalar = vec4(scalar.r);\n"
1857 " g_srcColor = vec4(0.0);\n";
1858
1859 if (property->GetTransferFunctionMode() == vtkVolumeProperty::TF_1D)
1860 {
1861 std::string gradientopacity_param = (property->HasGradientOpacity())
1862 ? input.GradientOpacityTablesMap[0] + std::string(", ")
1863 : std::string();
1864
1865 toShaderStr << " g_srcColor.a = computeOpacity(scalar,"
1866 << input.OpacityTablesMap[0]
1867 << ");\n"
1868 " if (g_srcColor.a > 0.0)\n"
1869 " {\n"
1870 " g_srcColor = computeColor(texPos, scalar, g_srcColor.a, "
1871 << input.RGBTablesMap[0] << ", " << gradientopacity_param << "in_volume[" << i
1872 << "], " << i << ");\n";
1873
1874 if (property->HasGradientOpacity())
1875 {
1876 const auto& grad = input.GradientCacheName;
1877 toShaderStr << " " << grad << "[0] = computeGradient(texPos, 0, "
1878 << "in_volume[" << i << "], " << i
1879 << ");\n"
1880 " if ("
1881 << grad
1882 << "[0].w >= 0.0)\n"
1883 " {\n"
1884 " g_srcColor.a *= computeGradientOpacity("
1885 << grad << "[0], " << input.GradientOpacityTablesMap[0]
1886 << ");\n"
1887 " }\n";
1888 }
1889 }
1890 else if (property->GetTransferFunctionMode() == vtkVolumeProperty::TF_2D)
1891 {
1892 const auto& grad = input.GradientCacheName;
1893 toShaderStr <<
1894 // Sample 2DTF directly
1895 " " << grad << "[0] = computeGradient(texPos, 0, "
1896 << "in_volume[" << i << "], " << i
1897 << ");\n"
1898 " g_srcColor = texture2D("
1899 << input.TransferFunctions2DMap[0] << ", vec2(scalar.r, "
1900 << input.GradientCacheName
1901 << "[0].w));\n"
1902 " if (g_srcColor.a > 0.0)\n"
1903 " {\n";
1904 }
1905
1906 toShaderStr
1907 << " g_srcColor.rgb *= g_srcColor.a;\n"
1908 " g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;\n"
1909 " }\n"
1910 " }\n\n";
1911
1912 i++;
1913 }
1914 }
1915 break;
1916 }
1917 toShaderStr << " }\n";
1918
1919 return toShaderStr.str();
1920}
1921
1922//--------------------------------------------------------------------------
1924 vtkVolume* vtkNotUsed(vol), vtkImageData* maskInput, vtkVolumeTexture* mask, int maskType,
1925 int noOfComponents, int independentComponents = 0)
1926{
1927 auto glMapper = vtkOpenGLGPUVolumeRayCastMapper::SafeDownCast(mapper);
1928
1929 std::string shaderStr;
1930
1931 shaderStr += std::string("\
1932 \n if (!g_skip)\
1933 \n {\
1934 \n vec4 scalar;\
1935 \n");
1937 {
1938 shaderStr += std::string("\
1939 \n // Compute IJK vertex position for current sample in the rectilinear grid\
1940 \n vec4 dataPosWorld = in_volumeMatrix[0] * in_textureDatasetMatrix[0] * vec4(g_dataPos, 1.0);\
1941 \n dataPosWorld = dataPosWorld / dataPosWorld.w;\
1942 \n dataPosWorld.w = 1.0;\
1943 \n ivec3 ijk = ivec3(0);\
1944 \n vec3 ijkTexCoord = vec3(0.0);\
1945 \n vec3 pCoords = vec3(0.0);\
1946 \n vec3 xPrev, xNext, tmp;\
1947 \n int sz = textureSize(in_coordTexs, 0);\
1948 \n vec4 dataPosWorldScaled = dataPosWorld * vec4(in_coordsScale, 1.0) +\
1949 \n vec4(in_coordsBias, 1.0);\
1950 \n for (int j = 0; j < 3; ++j)\
1951 \n {\
1952 \n xPrev = texture1D(in_coordTexs, 0.0).xyz;\
1953 \n xNext = texture1D(in_coordTexs, (in_coordTexSizes[j] - 1) / sz).xyz;\
1954 \n if (xNext[j] < xPrev[j])\
1955 \n {\
1956 \n tmp = xNext;\
1957 \n xNext = xPrev;\
1958 \n xPrev = tmp;\
1959 \n }\
1960 \n for (int i = 0; i < int(in_coordTexSizes[j]); i++)\
1961 \n {\
1962 \n xNext = texture1D(in_coordTexs, (i + 0.5) / sz).xyz;\
1963 \n if (dataPosWorldScaled[j] >= xPrev[j] && dataPosWorldScaled[j] < xNext[j])\
1964 \n {\
1965 \n ijk[j] = i - 1;\
1966 \n pCoords[j] = (dataPosWorldScaled[j] - xPrev[j]) / (xNext[j] - xPrev[j]);\
1967 \n break;\
1968 \n }\
1969 \n else if (dataPosWorldScaled[j] == xNext[j])\
1970 \n {\
1971 \n ijk[j] = i - 1;\
1972 \n pCoords[j] = 1.0;\
1973 \n break;\
1974 \n }\
1975 \n xPrev = xNext;\
1976 \n }\
1977 \n ijkTexCoord[j] = (ijk[j] + pCoords[j]) / in_coordTexSizes[j];\
1978 \n }\
1979 \n scalar = texture3D(in_volume[0], sign(in_cellSpacing[0]) * ijkTexCoord);\
1980 \n");
1981 }
1982 else
1983 {
1984 shaderStr += std::string("\
1985 \n scalar = texture3D(in_volume[0], g_dataPos);\
1986 \n");
1987 }
1988
1989 // simulate old intensity textures
1990 if (noOfComponents == 1)
1991 {
1992 shaderStr += std::string("\
1993 \n scalar.r = scalar.r * in_volume_scale[0].r + in_volume_bias[0].r;\
1994 \n scalar = vec4(scalar.r);");
1995 }
1996 else
1997 {
1998 // handle bias and scale
1999 shaderStr += std::string("\
2000 \n scalar = scalar * in_volume_scale[0] + in_volume_bias[0];");
2001 }
2002
2004 {
2005 if (noOfComponents > 1)
2006 {
2007 if (!independentComponents)
2008 {
2009 shaderStr += std::string("\
2010 \n if (l_maxValue.w < scalar.w || l_firstValue)\
2011 \n {\
2012 \n l_maxValue = scalar;\
2013 \n }\
2014 \n\
2015 \n if (l_firstValue)\
2016 \n {\
2017 \n l_firstValue = false;\
2018 \n }");
2019 }
2020 else
2021 {
2022 shaderStr += std::string("\
2023 \n for (int i = 0; i < in_noOfComponents; ++i)\
2024 \n {\
2025 \n if (l_maxValue[i] < scalar[i] || l_firstValue)\
2026 \n {\
2027 \n l_maxValue[i] = scalar[i];\
2028 \n }\
2029 \n }\
2030 \n if (l_firstValue)\
2031 \n {\
2032 \n l_firstValue = false;\
2033 \n }");
2034 }
2035 }
2036 else
2037 {
2038 shaderStr += std::string("\
2039 \n if (l_maxValue.w < scalar.x || l_firstValue)\
2040 \n {\
2041 \n l_maxValue.w = scalar.x;\
2042 \n }\
2043 \n\
2044 \n if (l_firstValue)\
2045 \n {\
2046 \n l_firstValue = false;\
2047 \n }");
2048 }
2049 }
2051 {
2052 if (noOfComponents > 1)
2053 {
2054 if (!independentComponents)
2055 {
2056 shaderStr += std::string("\
2057 \n if (l_minValue.w > scalar.w || l_firstValue)\
2058 \n {\
2059 \n l_minValue = scalar;\
2060 \n }\
2061 \n\
2062 \n if (l_firstValue)\
2063 \n {\
2064 \n l_firstValue = false;\
2065 \n }");
2066 }
2067 else
2068 {
2069 shaderStr += std::string("\
2070 \n for (int i = 0; i < in_noOfComponents; ++i)\
2071 \n {\
2072 \n if (l_minValue[i] < scalar[i] || l_firstValue)\
2073 \n {\
2074 \n l_minValue[i] = scalar[i];\
2075 \n }\
2076 \n }\
2077 \n if (l_firstValue)\
2078 \n {\
2079 \n l_firstValue = false;\
2080 \n }");
2081 }
2082 }
2083 else
2084 {
2085 shaderStr += std::string("\
2086 \n if (l_minValue.w > scalar.x || l_firstValue)\
2087 \n {\
2088 \n l_minValue.w = scalar.x;\
2089 \n }\
2090 \n\
2091 \n if (l_firstValue)\
2092 \n {\
2093 \n l_firstValue = false;\
2094 \n }");
2095 }
2096 }
2098 {
2099 if (noOfComponents > 1 && independentComponents)
2100 {
2101 shaderStr += std::string("\
2102 \n for (int i = 0; i < in_noOfComponents; ++i)\
2103 \n {\
2104 \n // Get the intensity in volume scalar range\
2105 \n float intensity = in_scalarsRange[i][0] +\
2106 \n (in_scalarsRange[i][1] -\
2107 \n in_scalarsRange[i][0]) * scalar[i];\
2108 \n if (in_averageIPRange.x <= intensity &&\
2109 \n intensity <= in_averageIPRange.y)\
2110 \n {\
2111 \n l_avgValue[i] += computeOpacity(scalar, i) * scalar[i];\
2112 \n ++l_numSamples[i];\
2113 \n }\
2114 \n }");
2115 }
2116 else
2117 {
2118 shaderStr += std::string("\
2119 \n // Get the intensity in volume scalar range\
2120 \n float intensity = in_scalarsRange[0][0] +\
2121 \n (in_scalarsRange[0][1] -\
2122 \n in_scalarsRange[0][0]) * scalar.x;\
2123 \n if (in_averageIPRange.x <= intensity &&\
2124 \n intensity <= in_averageIPRange.y)\
2125 \n {\
2126 \n l_avgValue.x += computeOpacity(scalar) * scalar.x;\
2127 \n ++l_numSamples.x;\
2128 \n }");
2129 }
2130 }
2131 else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
2132 {
2133 if (noOfComponents > 1 && independentComponents)
2134 {
2135 shaderStr += std::string("\
2136 \n for (int i = 0; i < in_noOfComponents; ++i)\
2137 \n {\
2138 \n float opacity = computeOpacity(scalar, i);\
2139 \n l_sumValue[i] = l_sumValue[i] + opacity * scalar[i];\
2140 \n }");
2141 }
2142 else
2143 {
2144 shaderStr += std::string("\
2145 \n float opacity = computeOpacity(scalar);\
2146 \n l_sumValue.x = l_sumValue.x + opacity * scalar.x;");
2147 }
2148 }
2149 else if (mapper->GetBlendMode() == vtkVolumeMapper::ISOSURFACE_BLEND)
2150 {
2151 shaderStr += std::string("\
2152 \n#if NUMBER_OF_CONTOURS\
2153 \n int maxComp = 0;");
2154
2155 std::string compParamStr = "";
2156 if (noOfComponents > 1 && independentComponents)
2157 {
2158 shaderStr += std::string("\
2159 \n for (int i = 1; i < in_noOfComponents; ++i)\
2160 \n {\
2161 \n if (in_componentWeight[i] > in_componentWeight[maxComp])\
2162 \n maxComp = i;\
2163 \n }");
2164 compParamStr = ", maxComp";
2165 }
2166 shaderStr += std::string("\
2167 \n if (g_currentT == 0)\
2168 \n {\
2169 \n l_initialIndex = findIsoSurfaceIndex(scalar[maxComp], l_normValues);\
2170 \n }\
2171 \n else\
2172 \n {\
2173 \n float s;\
2174 \n bool shade = false;\
2175 \n l_initialIndex = clamp(l_initialIndex, 0, NUMBER_OF_CONTOURS);\
2176 \n if (scalar[maxComp] < l_normValues[l_initialIndex])\
2177 \n {\
2178 \n s = l_normValues[l_initialIndex];\
2179 \n l_initialIndex--;\
2180 \n shade = true;\
2181 \n }\
2182 \n if (scalar[maxComp] > l_normValues[l_initialIndex+1])\
2183 \n {\
2184 \n s = l_normValues[l_initialIndex+1];\
2185 \n l_initialIndex++;\
2186 \n shade = true;\
2187 \n }\
2188 \n if (shade == true)\
2189 \n {\
2190 \n vec4 vs = vec4(s);\
2191 \n g_srcColor.a = computeOpacity(vs " +
2192 compParamStr + ");\
2193 \n g_srcColor = computeColor(vs, g_srcColor.a " +
2194 compParamStr + ");\
2195 \n g_srcColor.rgb *= g_srcColor.a;\
2196 \n g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;\
2197 \n }\
2198 \n }\
2199 \n#endif");
2200 }
2201 else if (mapper->GetBlendMode() == vtkVolumeMapper::SLICE_BLEND)
2202 {
2203 shaderStr += std::string("\
2204 \n // test if the intersection is inside the volume bounds\
2205 \n if (any(greaterThan(g_dataPos, vec3(1.0))) || any(lessThan(g_dataPos, vec3(0.0))))\
2206 \n {\
2207 \n discard;\
2208 \n }\
2209 \n float opacity = computeOpacity(scalar);\
2210 \n g_fragColor = computeColor(scalar, opacity);\
2211 \n g_fragColor.rgb *= opacity;\
2212 \n g_exit = true;");
2213 }
2214 else if (mapper->GetBlendMode() == vtkVolumeMapper::COMPOSITE_BLEND)
2215 {
2216 if (noOfComponents > 1 && independentComponents)
2217 {
2218 shaderStr += std::string("\
2219 \n vec4 color[4]; vec4 tmp = vec4(0.0);\
2220 \n float totalAlpha = 0.0;\
2221 \n for (int i = 0; i < in_noOfComponents; ++i)\
2222 \n {\
2223 ");
2224 if (glMapper->GetUseDepthPass() &&
2225 glMapper->GetCurrentPass() == vtkOpenGLGPUVolumeRayCastMapper::DepthPass)
2226 {
2227 shaderStr += std::string("\
2228 \n // Data fetching from the red channel of volume texture\
2229 \n float opacity = computeOpacity(scalar, i);\
2230 \n if (opacity > 0.0)\
2231 \n {\
2232 \n g_srcColor.a = opacity;\
2233 \n }\
2234 \n }");
2235 }
2236 else if (!mask || !maskInput || maskType != vtkGPUVolumeRayCastMapper::LabelMapMaskType)
2237 {
2238 shaderStr += std::string("\
2239 \n // Data fetching from the red channel of volume texture\
2240 \n color[i][3] = computeOpacity(scalar, i);\
2241 \n color[i] = computeColor(scalar, color[i][3], i);\
2242 \n totalAlpha += color[i][3] * in_componentWeight[i];\
2243 \n }\
2244 \n if (totalAlpha > 0.0)\
2245 \n {\
2246 \n for (int i = 0; i < in_noOfComponents; ++i)\
2247 \n {\
2248 \n // Only let visible components contribute to the final color\
2249 \n if (in_componentWeight[i] <= 0) continue;\
2250 \n\
2251 \n tmp.x += color[i].x * color[i].w * in_componentWeight[i];\
2252 \n tmp.y += color[i].y * color[i].w * in_componentWeight[i];\
2253 \n tmp.z += color[i].z * color[i].w * in_componentWeight[i];\
2254 \n tmp.w += ((color[i].w * color[i].w)/totalAlpha);\
2255 \n }\
2256 \n }\
2257 \n g_fragColor = (1.0f - g_fragColor.a) * tmp + g_fragColor;");
2258 }
2259 }
2260 else if (glMapper->GetUseDepthPass() &&
2261 glMapper->GetCurrentPass() == vtkOpenGLGPUVolumeRayCastMapper::DepthPass)
2262 {
2263 shaderStr += std::string("\
2264 \n g_srcColor = vec4(0.0);\
2265 \n g_srcColor.a = computeOpacity(scalar);");
2266 }
2267 else
2268 {
2269 if (!mask || !maskInput || maskType != vtkGPUVolumeRayCastMapper::LabelMapMaskType)
2270 {
2271 shaderStr += std::string("\
2272 \n g_srcColor = vec4(0.0);\
2273 \n g_srcColor.a = computeOpacity(scalar);\
2274 \n if (g_srcColor.a > 0.0)\
2275 \n {\
2276 \n g_srcColor = computeColor(scalar, g_srcColor.a);");
2277 }
2278
2279 shaderStr += std::string("\
2280 \n // Opacity calculation using compositing:\
2281 \n // Here we use front to back compositing scheme whereby\
2282 \n // the current sample value is multiplied to the\
2283 \n // currently accumulated alpha and then this product\
2284 \n // is subtracted from the sample value to get the\
2285 \n // alpha from the previous steps. Next, this alpha is\
2286 \n // multiplied with the current sample colour\
2287 \n // and accumulated to the composited colour. The alpha\
2288 \n // value from the previous steps is then accumulated\
2289 \n // to the composited colour alpha.\
2290 \n g_srcColor.rgb *= g_srcColor.a;\
2291 \n g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;");
2292
2293 if (!mask || !maskInput || maskType != vtkGPUVolumeRayCastMapper::LabelMapMaskType)
2294 {
2295 shaderStr += std::string("\
2296 \n }");
2297 }
2298 }
2299 }
2300 else
2301 {
2302 shaderStr += std::string();
2303 }
2304
2305 shaderStr += std::string("\
2306 \n }");
2307 return shaderStr;
2308}
2309
2310//--------------------------------------------------------------------------
2312 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2313{
2314 return std::string("\
2315 \n // Special coloring mode which renders the Prop Id in fragments that\
2316 \n // have accumulated certain level of opacity. Used during the selection\
2317 \n // pass vtkHardwareSelection::ACTOR_PASS.\
2318 \n if (g_fragColor.a > 3.0/ 255.0)\
2319 \n {\
2320 \n gl_FragData[0] = vec4(in_propId, 1.0);\
2321 \n }\
2322 \n else\
2323 \n {\
2324 \n gl_FragData[0] = vec4(0.0);\
2325 \n }\
2326 \n return;");
2327};
2328
2329//--------------------------------------------------------------------------
2331 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2332{
2333 return std::string("\
2334 \n // Special coloring mode which renders the voxel index in fragments that\
2335 \n // have accumulated certain level of opacity. Used during the selection\
2336 \n // pass vtkHardwareSelection::ID_LOW24.\
2337 \n if (g_fragColor.a > 3.0/ 255.0)\
2338 \n {\
2339 \n uvec3 volumeDim = uvec3(in_textureExtentsMax - in_textureExtentsMin);\
2340 \n uvec3 voxelCoords = uvec3(volumeDim * g_dataPos);\
2341 \n // vtkHardwareSelector assumes index 0 to be empty space, so add uint(1).\
2342 \n uint idx = volumeDim.x * volumeDim.y * voxelCoords.z +\
2343 \n volumeDim.x * voxelCoords.y + voxelCoords.x + uint(1);\
2344 \n gl_FragData[0] = vec4(float(idx % uint(256)) / 255.0,\
2345 \n float((idx / uint(256)) % uint(256)) / 255.0,\
2346 \n float((idx / uint(65536)) % uint(256)) / 255.0, 1.0);\
2347 \n }\
2348 \n else\
2349 \n {\
2350 \n gl_FragData[0] = vec4(0.0);\
2351 \n }\
2352 \n return;");
2353};
2354
2355//--------------------------------------------------------------------------
2357 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2358{
2359 return std::string("\
2360 \n // Special coloring mode which renders the voxel index in fragments that\
2361 \n // have accumulated certain level of opacity. Used during the selection\
2362 \n // pass vtkHardwareSelection::ID_MID24.\
2363 \n if (g_fragColor.a > 3.0/ 255.0)\
2364 \n {\
2365 \n uvec3 volumeDim = uvec3(in_textureExtentsMax - in_textureExtentsMin);\
2366 \n uvec3 voxelCoords = uvec3(volumeDim * g_dataPos);\
2367 \n // vtkHardwareSelector assumes index 0 to be empty space, so add uint(1).\
2368 \n uint idx = volumeDim.x * volumeDim.y * voxelCoords.z +\
2369 \n volumeDim.x * voxelCoords.y + voxelCoords.x + uint(1);\
2370 \n idx = ((idx & 0xff000000) >> 24);\
2371 \n gl_FragData[0] = vec4(float(idx % uint(256)) / 255.0,\
2372 \n float((idx / uint(256)) % uint(256)) / 255.0,\
2373 \n float(idx / uint(65536)) / 255.0, 1.0);\
2374 \n }\
2375 \n else\
2376 \n {\
2377 \n gl_FragData[0] = vec4(0.0);\
2378 \n }\
2379 \n return;");
2380};
2381
2382//--------------------------------------------------------------------------
2384 vtkVolume* vtkNotUsed(vol), int noOfComponents, int independentComponents = 0)
2385{
2387
2388 if (glMapper->GetUseDepthPass() &&
2391 {
2392 return std::string();
2393 }
2395 {
2396 if (noOfComponents > 1 && independentComponents)
2397 {
2398 return std::string("\
2399 \n g_srcColor = vec4(0);\
2400 \n for (int i = 0; i < in_noOfComponents; ++i)\
2401 \n {\
2402 \n vec4 tmp = computeColor(l_maxValue, computeOpacity(l_maxValue, i), i);\
2403 \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
2404 \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
2405 \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
2406 \n g_srcColor[3] += tmp[3] * in_componentWeight[i];\
2407 \n }\
2408 \n g_fragColor = g_srcColor;");
2409 }
2410 else
2411 {
2412 return std::string("\
2413 \n g_srcColor = computeColor(l_maxValue,\
2414 \n computeOpacity(l_maxValue));\
2415 \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
2416 \n g_fragColor.a = g_srcColor.a;");
2417 }
2418 }
2420 {
2421 if (noOfComponents > 1 && independentComponents)
2422 {
2423 return std::string("\
2424 \n g_srcColor = vec4(0);\
2425 \n for (int i = 0; i < in_noOfComponents; ++i)\
2426 \n {\
2427 \n vec4 tmp = computeColor(l_minValue, computeOpacity(l_minValue, i), i);\
2428 \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
2429 \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
2430 \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
2431 \n g_srcColor[2] += tmp[3] * tmp[3] * in_componentWeight[i];\
2432 \n }\
2433 \n g_fragColor = g_srcColor;");
2434 }
2435 else
2436 {
2437 return std::string("\
2438 \n g_srcColor = computeColor(l_minValue,\
2439 \n computeOpacity(l_minValue));\
2440 \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
2441 \n g_fragColor.a = g_srcColor.a;");
2442 }
2443 }
2445 {
2446 if (noOfComponents > 1 && independentComponents)
2447 {
2448 return std::string("\
2449 \n for (int i = 0; i < in_noOfComponents; ++i)\
2450 \n {\
2451 \n if (l_numSamples[i] == uint(0))\
2452 \n {\
2453 \n continue;\
2454 \n }\
2455 \n l_avgValue[i] = l_avgValue[i] * in_componentWeight[i] /\
2456 \n l_numSamples[i];\
2457 \n if (i > 0)\
2458 \n {\
2459 \n l_avgValue[0] += l_avgValue[i];\
2460 \n }\
2461 \n }\
2462 \n l_avgValue[0] = clamp(l_avgValue[0], 0.0, 1.0);\
2463 \n g_fragColor = vec4(vec3(l_avgValue[0]), 1.0);");
2464 }
2465 else
2466 {
2467 return std::string("\
2468 \n if (l_numSamples.x == uint(0))\
2469 \n {\
2470 \n discard;\
2471 \n }\
2472 \n else\
2473 \n {\
2474 \n l_avgValue.x /= l_numSamples.x;\
2475 \n l_avgValue.x = clamp(l_avgValue.x, 0.0, 1.0);\
2476 \n g_fragColor = vec4(vec3(l_avgValue.x), 1.0);\
2477 \n }");
2478 }
2479 }
2480 else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
2481 {
2482 if (noOfComponents > 1 && independentComponents)
2483 {
2484 // Add all the components to get final color
2485 return std::string("\
2486 \n l_sumValue.x *= in_componentWeight.x;\
2487 \n for (int i = 1; i < in_noOfComponents; ++i)\
2488 \n {\
2489 \n l_sumValue.x += l_sumValue[i] * in_componentWeight[i];\
2490 \n }\
2491 \n l_sumValue.x = clamp(l_sumValue.x, 0.0, 1.0);\
2492 \n g_fragColor = vec4(vec3(l_sumValue.x), 1.0);");
2493 }
2494 else
2495 {
2496 return std::string("\
2497 \n l_sumValue.x = clamp(l_sumValue.x, 0.0, 1.0);\
2498 \n g_fragColor = vec4(vec3(l_sumValue.x), 1.0);");
2499 }
2500 }
2501 else
2502 {
2503 return std::string();
2504 }
2505}
2506
2507//--------------------------------------------------------------------------
2509 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2510{
2511 return std::string();
2512}
2513
2514//--------------------------------------------------------------------------
2516 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2517{
2518 return std::string("\
2519 \n const float g_opacityThreshold = 1.0 - 1.0 / 255.0;");
2520}
2521
2522//--------------------------------------------------------------------------
2524 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2525{
2526 return std::string("\
2527 \n uniform vec3 in_propId;");
2528};
2529
2530//--------------------------------------------------------------------------
2532{
2533 std::string shaderStr;
2534 shaderStr += std::string("\
2535 \n // Flag to indicate if the raymarch loop should terminate \
2536 \n bool stop = false;\
2537 \n\
2538 \n g_terminatePointMax = 0.0;\
2539 \n\
2540 \n vec4 l_depthValue = texture2D(in_depthSampler, fragTexCoord);\
2541 \n // Depth test\
2542 \n if(gl_FragCoord.z >= l_depthValue.x)\
2543 \n {\
2544 \n discard;\
2545 \n }\
2546 \n\
2547 \n // color buffer or max scalar buffer have a reduced size.\
2548 \n fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
2549 \n in_inverseOriginalWindowSize;\
2550 \n");
2551
2553 {
2554 vtkImplicitFunction* sliceFunc = vol->GetProperty()->GetSliceFunction();
2555 if (sliceFunc)
2556 {
2557 if (sliceFunc->IsA("vtkPlane"))
2558 {
2559 shaderStr += std::string("\
2560 \n\
2561 \n // Intersection with plane\
2562 \n float t = intersectRayPlane(ip_vertexPos, rayDir);\
2563 \n vec4 intersection = vec4(ip_vertexPos + t * rayDir, 1.0);\
2564 \n g_intersection = (in_inverseTextureDatasetMatrix[0] * intersection).xyz;\
2565 \n vec4 intersDC = in_projectionMatrix * in_modelViewMatrix * in_volumeMatrix[0] * intersection;\
2566 \n intersDC.xyz /= intersDC.w;\
2567 \n vec4 intersWin = NDCToWindow(intersDC.x, intersDC.y, intersDC.z);\
2568 \n if(intersWin.z >= l_depthValue.x)\
2569 \n {\
2570 \n discard;\
2571 \n }\
2572 \n");
2573 }
2574 else
2575 {
2576 vtkErrorWithObjectMacro(
2577 sliceFunc, "Implicit function type is not supported by this mapper.");
2578 }
2579 }
2580 }
2581
2582 shaderStr += std::string("\
2583 \n // Compute max number of iterations it will take before we hit\
2584 \n // the termination point\
2585 \n\
2586 \n // Abscissa of the point on the depth buffer along the ray.\
2587 \n // point in texture coordinates\
2588 \n vec4 rayTermination = WindowToNDC(gl_FragCoord.x, gl_FragCoord.y, l_depthValue.x);\
2589 \n\
2590 \n // From normalized device coordinates to eye coordinates.\
2591 \n // in_projectionMatrix is inversed because of way VT\
2592 \n // From eye coordinates to texture coordinates\
2593 \n rayTermination = ip_inverseTextureDataAdjusted *\
2594 \n in_inverseVolumeMatrix[0] *\
2595 \n in_inverseModelViewMatrix *\
2596 \n in_inverseProjectionMatrix *\
2597 \n rayTermination;\
2598 \n g_rayTermination = rayTermination.xyz / rayTermination.w;\
2599 \n\
2600 \n // Setup the current segment:\
2601 \n g_dataPos = g_rayOrigin;\
2602 \n g_terminatePos = g_rayTermination;\
2603 \n\
2604 \n g_terminatePointMax = length(g_terminatePos.xyz - g_dataPos.xyz) /\
2605 \n length(g_dirStep);\
2606 \n g_currentT = 0.0;");
2607
2608 return shaderStr;
2609}
2610
2611//--------------------------------------------------------------------------
2613 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2614{
2615 return std::string("\
2616 \n if(any(greaterThan(max(g_dirStep, vec3(0.0))*(g_dataPos - in_texMax[0]),vec3(0.0))) ||\
2617 \n any(greaterThan(min(g_dirStep, vec3(0.0))*(g_dataPos - in_texMin[0]),vec3(0.0))))\
2618 \n {\
2619 \n break;\
2620 \n }\
2621 \n\
2622 \n // Early ray termination\
2623 \n // if the currently composited colour alpha is already fully saturated\
2624 \n // we terminated the loop or if we have hit an obstacle in the\
2625 \n // direction of they ray (using depth buffer) we terminate as well.\
2626 \n if((g_fragColor.a > g_opacityThreshold) || \
2627 \n g_currentT >= g_terminatePointMax)\
2628 \n {\
2629 \n break;\
2630 \n }\
2631 \n ++g_currentT;");
2632}
2633
2634//--------------------------------------------------------------------------
2636 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2637{
2638 return std::string();
2639}
2640
2641//--------------------------------------------------------------------------
2643 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2644{
2645 return std::string();
2646}
2647
2648//--------------------------------------------------------------------------
2650 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
2651{
2652 if (!mapper->GetCropping())
2653 {
2654 return std::string();
2655 }
2656
2657 return std::string("\
2658 \nuniform float in_croppingPlanes[6];\
2659 \nuniform int in_croppingFlags [32];\
2660 \nfloat croppingPlanesTexture[6];\
2661 \n\
2662 \n// X: axis = 0, Y: axis = 1, Z: axis = 2\
2663 \n// cp Cropping plane bounds (minX, maxX, minY, maxY, minZ, maxZ)\
2664 \nint computeRegionCoord(float cp[6], vec3 pos, int axis)\
2665 \n {\
2666 \n int cpmin = axis * 2;\
2667 \n int cpmax = cpmin + 1;\
2668 \n\
2669 \n if (pos[axis] < cp[cpmin])\
2670 \n {\
2671 \n return 1;\
2672 \n }\
2673 \n else if (pos[axis] >= cp[cpmin] &&\
2674 \n pos[axis] < cp[cpmax])\
2675 \n {\
2676 \n return 2;\
2677 \n }\
2678 \n else if (pos[axis] >= cp[cpmax])\
2679 \n {\
2680 \n return 3;\
2681 \n }\
2682 \n return 0;\
2683 \n }\
2684 \n\
2685 \nint computeRegion(float cp[6], vec3 pos)\
2686 \n {\
2687 \n return (computeRegionCoord(cp, pos, 0) +\
2688 \n (computeRegionCoord(cp, pos, 1) - 1) * 3 +\
2689 \n (computeRegionCoord(cp, pos, 2) - 1) * 9);\
2690 \n }");
2691}
2692
2693//--------------------------------------------------------------------------
2695 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
2696{
2697 if (!mapper->GetCropping())
2698 {
2699 return std::string();
2700 }
2701
2702 return std::string("\
2703 \n // Convert cropping region to texture space\
2704 \n mat4 datasetToTextureMat = in_inverseTextureDatasetMatrix[0];\
2705 \n\
2706 \n vec4 tempCrop = vec4(in_croppingPlanes[0], 0.0, 0.0, 1.0);\
2707 \n tempCrop = datasetToTextureMat * tempCrop;\
2708 \n if (tempCrop[3] != 0.0)\
2709 \n {\
2710 \n tempCrop[0] /= tempCrop[3];\
2711 \n }\
2712 \n croppingPlanesTexture[0] = tempCrop[0];\
2713 \n\
2714 \n tempCrop = vec4(in_croppingPlanes[1], 0.0, 0.0, 1.0);\
2715 \n tempCrop = datasetToTextureMat * tempCrop;\
2716 \n if (tempCrop[3] != 0.0)\
2717 \n {\
2718 \n tempCrop[0] /= tempCrop[3];\
2719 \n }\
2720 \n croppingPlanesTexture[1] = tempCrop[0];\
2721 \n\
2722 \n tempCrop = vec4(0.0, in_croppingPlanes[2], 0.0, 1.0);\
2723 \n tempCrop = datasetToTextureMat * tempCrop;\
2724 \n if (tempCrop[3] != 0.0)\
2725 \n {\
2726 \n tempCrop[1] /= tempCrop[3];\
2727 \n }\
2728 \n croppingPlanesTexture[2] = tempCrop[1];\
2729 \n\
2730 \n tempCrop = vec4(0.0, in_croppingPlanes[3], 0.0, 1.0);\
2731 \n tempCrop = datasetToTextureMat * tempCrop;\
2732 \n if (tempCrop[3] != 0.0)\
2733 \n {\
2734 \n tempCrop[1] /= tempCrop[3];\
2735 \n }\
2736 \n croppingPlanesTexture[3] = tempCrop[1];\
2737 \n\
2738 \n tempCrop = vec4(0.0, 0.0, in_croppingPlanes[4], 1.0);\
2739 \n tempCrop = datasetToTextureMat * tempCrop;\
2740 \n if (tempCrop[3] != 0.0)\
2741 \n {\
2742 \n tempCrop[2] /= tempCrop[3];\
2743 \n }\
2744 \n croppingPlanesTexture[4] = tempCrop[2];\
2745 \n\
2746 \n tempCrop = vec4(0.0, 0.0, in_croppingPlanes[5], 1.0);\
2747 \n tempCrop = datasetToTextureMat * tempCrop;\
2748 \n if (tempCrop[3] != 0.0)\
2749 \n {\
2750 \n tempCrop[2] /= tempCrop[3];\
2751 \n }\
2752 \n croppingPlanesTexture[5] = tempCrop[2];");
2753}
2754
2755//--------------------------------------------------------------------------
2757 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
2758{
2759 if (!mapper->GetCropping())
2760 {
2761 return std::string();
2762 }
2763
2764 return std::string("\
2765 \n // Determine region\
2766 \n int regionNo = computeRegion(croppingPlanesTexture, g_dataPos);\
2767 \n\
2768 \n // Do & operation with cropping flags\
2769 \n // Pass the flag that its Ok to sample or not to sample\
2770 \n if (in_croppingFlags[regionNo] == 0)\
2771 \n {\
2772 \n // Skip this voxel\
2773 \n g_skip = true;\
2774 \n }");
2775}
2776
2777//--------------------------------------------------------------------------
2779 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2780{
2781 return std::string();
2782}
2783
2784//--------------------------------------------------------------------------
2786 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2787{
2788 return std::string();
2789}
2790
2791//--------------------------------------------------------------------------
2793 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
2794{
2795 if (!mapper->GetClippingPlanes())
2796 {
2797 return std::string();
2798 }
2799
2800 return std::string("\
2801 \n /// We support only 8 clipping planes for now\
2802 \n /// The first value is the size of the data array for clipping\
2803 \n /// planes (origin, normal)\
2804 \n uniform float in_clippingPlanes[49];\
2805 \n uniform float in_clippedVoxelIntensity;\
2806 \n\
2807 \n int clip_numPlanes;\
2808 \n vec3 clip_rayDirObj;\
2809 \n mat4 clip_texToObjMat;\
2810 \n mat4 clip_objToTexMat;\
2811 \n\
2812 \n// Tighten the sample range as needed to account for clip planes. \
2813 \n// Arguments are in texture coordinates. \
2814 \n// Returns true if the range is at all valid after clipping. If not, \
2815 \n// the fragment should be discarded. \
2816 \nbool AdjustSampleRangeForClipping(inout vec3 startPosTex, inout vec3 stopPosTex) \
2817 \n{ \
2818 \n vec4 startPosObj = vec4(0.0);\
2819 \n {\
2820 \n startPosObj = clip_texToObjMat * vec4(startPosTex - g_rayJitter, 1.0);\
2821 \n startPosObj = startPosObj / startPosObj.w;\
2822 \n startPosObj.w = 1.0;\
2823 \n }\
2824 \n\
2825 \n vec4 stopPosObj = vec4(0.0);\
2826 \n {\
2827 \n stopPosObj = clip_texToObjMat * vec4(stopPosTex, 1.0);\
2828 \n stopPosObj = stopPosObj / stopPosObj.w;\
2829 \n stopPosObj.w = 1.0;\
2830 \n }\
2831 \n\
2832 \n for (int i = 0; i < clip_numPlanes; i = i + 6)\
2833 \n {\
2834 \n vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\
2835 \n in_clippingPlanes[i + 2],\
2836 \n in_clippingPlanes[i + 3]);\
2837 \n vec3 planeNormal = normalize(vec3(in_clippingPlanes[i + 4],\
2838 \n in_clippingPlanes[i + 5],\
2839 \n in_clippingPlanes[i + 6]));\
2840 \n\
2841 \n // Abort if the entire segment is clipped:\
2842 \n // (We can do this before adjusting the term point, since it'll \
2843 \n // only move further into the clipped area)\
2844 \n float startDistance = dot(planeNormal, planeOrigin - startPosObj.xyz);\
2845 \n float stopDistance = dot(planeNormal, planeOrigin - stopPosObj.xyz);\
2846 \n bool startClipped = startDistance > 0.0;\
2847 \n bool stopClipped = stopDistance > 0.0;\
2848 \n if (startClipped && stopClipped)\
2849 \n {\
2850 \n return false;\
2851 \n }\
2852 \n\
2853 \n float rayDotNormal = dot(clip_rayDirObj, planeNormal);\
2854 \n bool frontFace = rayDotNormal > 0.0;\
2855 \n\
2856 \n // Move the start position further from the eye if needed:\
2857 \n if (frontFace && // Observing from the clipped side (plane's front face)\
2858 \n startDistance > 0.0) // Ray-entry lies on the clipped side.\
2859 \n {\
2860 \n // Scale the point-plane distance to the ray direction and update the\
2861 \n // entry point.\
2862 \n float rayScaledDist = startDistance / rayDotNormal;\
2863 \n startPosObj = vec4(startPosObj.xyz + rayScaledDist * clip_rayDirObj, 1.0);\
2864 \n vec4 newStartPosTex = clip_objToTexMat * vec4(startPosObj.xyz, 1.0);\
2865 \n newStartPosTex /= newStartPosTex.w;\
2866 \n startPosTex = newStartPosTex.xyz;\
2867 \n startPosTex += g_rayJitter;\
2868 \n }\
2869 \n\
2870 \n // Move the end position closer to the eye if needed:\
2871 \n if (!frontFace && // Observing from the unclipped side (plane's back face)\
2872 \n stopDistance > 0.0) // Ray-entry lies on the unclipped side.\
2873 \n {\
2874 \n // Scale the point-plane distance to the ray direction and update the\
2875 \n // termination point.\
2876 \n float rayScaledDist = stopDistance / rayDotNormal;\
2877 \n stopPosObj = vec4(stopPosObj.xyz + rayScaledDist * clip_rayDirObj, 1.0);\
2878 \n vec4 newStopPosTex = clip_objToTexMat * vec4(stopPosObj.xyz, 1.0);\
2879 \n newStopPosTex /= newStopPosTex.w;\
2880 \n stopPosTex = newStopPosTex.xyz;\
2881 \n }\
2882 \n }\
2883 \n\
2884 \n if (any(greaterThan(startPosTex, in_texMax[0])) ||\
2885 \n any(lessThan(startPosTex, in_texMin[0])))\
2886 \n {\
2887 \n return false;\
2888 \n }\
2889 \n\
2890 \n return true;\
2891 \n}\
2892 \n");
2893}
2894
2895//--------------------------------------------------------------------------
2897{
2898 if (!mapper->GetClippingPlanes())
2899 {
2900 return std::string();
2901 }
2902
2903 std::string shaderStr;
2905 {
2906 shaderStr = std::string("\
2907 \n vec4 tempClip = in_volumeMatrix[0] * vec4(rayDir, 0.0);\
2908 \n if (tempClip.w != 0.0)\
2909 \n {\
2910 \n tempClip = tempClip/tempClip.w;\
2911 \n tempClip.w = 1.0;\
2912 \n }\
2913 \n clip_rayDirObj = normalize(tempClip.xyz);");
2914 }
2915 else
2916 {
2917 shaderStr = std::string("\
2918 clip_rayDirObj = normalize(in_projectionDirection);");
2919 }
2920
2921 shaderStr += std::string("\
2922 \n clip_numPlanes = int(in_clippingPlanes[0]);\
2923 \n clip_texToObjMat = in_volumeMatrix[0] * in_textureDatasetMatrix[0];\
2924 \n clip_objToTexMat = in_inverseTextureDatasetMatrix[0] * in_inverseVolumeMatrix[0];\
2925 \n\
2926 \n // Adjust for clipping.\
2927 \n if (!AdjustSampleRangeForClipping(g_rayOrigin, g_rayTermination))\
2928 \n { // entire ray is clipped.\
2929 \n discard;\
2930 \n }\
2931 \n\
2932 \n // Update the segment post-clip:\
2933 \n g_dataPos = g_rayOrigin;\
2934 \n g_terminatePos = g_rayTermination;\
2935 \n g_terminatePointMax = length(g_terminatePos.xyz - g_dataPos.xyz) /\
2936 \n length(g_dirStep);\
2937 \n");
2938
2939 return shaderStr;
2940}
2941
2942//--------------------------------------------------------------------------
2944 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2945{
2946 return std::string();
2947}
2948
2949//--------------------------------------------------------------------------
2951 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2952{
2953 return std::string();
2954}
2955
2956//--------------------------------------------------------------------------
2957std::string BinaryMaskDeclaration(vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper),
2958 vtkVolume* vtkNotUsed(vol), vtkImageData* maskInput, vtkVolumeTexture* mask,
2959 int vtkNotUsed(maskType))
2960{
2961 if (!mask || !maskInput)
2962 {
2963 return std::string();
2964 }
2965 else
2966 {
2967 return std::string("uniform sampler3D in_mask;");
2968 }
2969}
2970
2971//--------------------------------------------------------------------------
2973 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), vtkImageData* maskInput,
2974 vtkVolumeTexture* mask, int maskType)
2975{
2976 if (!mask || !maskInput || maskType == vtkGPUVolumeRayCastMapper::LabelMapMaskType)
2977 {
2978 return std::string();
2979 }
2980 else
2981 {
2982 return std::string("\
2983 \nvec4 maskValue = texture3D(in_mask, g_dataPos);\
2984 \nif(maskValue.r <= 0.0)\
2985 \n {\
2986 \n g_skip = true;\
2987 \n }");
2988 }
2989}
2990
2991//--------------------------------------------------------------------------
2993 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), vtkImageData* maskInput,
2994 vtkVolumeTexture* mask, int maskType)
2995{
2996 if (!mask || !maskInput || maskType != vtkGPUVolumeRayCastMapper::LabelMapMaskType)
2997 {
2998 return std::string();
2999 }
3000 else
3001 {
3002 return std::string("\
3003 \nuniform float in_maskBlendFactor;\
3004 \nuniform sampler2D in_labelMapTransfer;\
3005 \nuniform float in_mask_scale;\
3006 \nuniform float in_mask_bias;\
3007 \nuniform int in_labelMapNumLabels;\
3008 \n");
3009 }
3010}
3011
3012//--------------------------------------------------------------------------
3014 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), vtkImageData* maskInput,
3015 vtkVolumeTexture* mask, int maskType, int noOfComponents)
3016{
3017 if (!mask || !maskInput || maskType != vtkGPUVolumeRayCastMapper::LabelMapMaskType)
3018 {
3019 return std::string();
3020 }
3021 else
3022 {
3023 std::string shaderStr = std::string("\
3024 \nvec4 scalar = texture3D(in_volume[0], g_dataPos);");
3025
3026 // simulate old intensity textures
3027 if (noOfComponents == 1)
3028 {
3029 shaderStr += std::string("\
3030 \n scalar.r = scalar.r * in_volume_scale[0].r + in_volume_bias[0].r;\
3031 \n scalar = vec4(scalar.r);");
3032 }
3033 else
3034 {
3035 // handle bias and scale
3036 shaderStr += std::string("\
3037 \n scalar = scalar * in_volume_scale[0] + in_volume_bias[0];");
3038 }
3039
3040 // Assumeing single component scalar for label texture lookup.
3041 // This can be extended to composite color obtained from all components
3042 // in the scalar array.
3043 return shaderStr + std::string("\
3044 \nif (in_maskBlendFactor == 0.0)\
3045 \n {\
3046 \n g_srcColor.a = computeOpacity(scalar);\
3047 \n if (g_srcColor.a > 0)\
3048 \n {\
3049 \n g_srcColor = computeColor(scalar, g_srcColor.a);\
3050 \n }\
3051 \n }\
3052 \nelse\
3053 \n {\
3054 \n float opacity = computeOpacity(scalar);\
3055 \n // Get the mask value at this same location\
3056 \n vec4 maskValue = texture3D(in_mask, g_dataPos);\
3057 \n maskValue.r = maskValue.r * in_mask_scale + in_mask_bias;\
3058 \n // Quantize the height of the labelmap texture over number of labels\
3059 \n if (in_labelMapNumLabels > 0)\
3060 \n {\
3061 \n maskValue.r =\
3062 \n floor(maskValue.r * in_labelMapNumLabels) /\
3063 \n in_labelMapNumLabels;\
3064 \n }\
3065 \n else\
3066 \n {\
3067 \n maskValue.r = 0.0;\
3068 \n }\
3069 \n if(maskValue.r == 0.0)\
3070 \n {\
3071 \n g_srcColor.a = opacity;\
3072 \n if (g_srcColor.a > 0)\
3073 \n {\
3074 \n g_srcColor = computeColor(scalar, g_srcColor.a);\
3075 \n }\
3076 \n }\
3077 \n else\
3078 \n {\
3079 \n g_srcColor = texture2D(in_labelMapTransfer,\
3080 \n vec2(scalar.r, maskValue.r));\
3081 \n if (g_srcColor.a > 0)\
3082 \n {\
3083 \n g_srcColor = computeLighting(g_srcColor, 0, maskValue.r);\
3084 \n }\
3085 \n if (in_maskBlendFactor < 1.0)\
3086 \n {\
3087 \n vec4 color = opacity > 0 ? computeColor(scalar, opacity) : vec4(0);\
3088 \n g_srcColor = (1.0 - in_maskBlendFactor) * color +\
3089 \n in_maskBlendFactor * g_srcColor;\
3090 \n }\
3091 \n }\
3092 \n }");
3093 }
3094}
3095
3096//--------------------------------------------------------------------------
3098 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3099{
3100 return std::string("uniform bool in_clampDepthToBackface;\n"
3101 "vec3 l_opaqueFragPos;\n"
3102 "bool l_updateDepth;\n");
3103}
3104
3105//--------------------------------------------------------------------------
3107 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3108{
3109 return std::string("\
3110 \n l_opaqueFragPos = vec3(-1.0);\
3111 \n if(in_clampDepthToBackface)\
3112 \n {\
3113 \n l_opaqueFragPos = g_dataPos;\
3114 \n }\
3115 \n l_updateDepth = true;");
3116}
3117
3118//--------------------------------------------------------------------------
3120 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3121{
3122 return std::string("\
3123 \n if(!g_skip && g_srcColor.a > 0.0 && l_updateDepth)\
3124 \n {\
3125 \n l_opaqueFragPos = g_dataPos;\
3126 \n l_updateDepth = false;\
3127 \n }");
3128}
3129
3130//--------------------------------------------------------------------------
3132 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3133{
3134 return std::string("\
3135 \n if (l_opaqueFragPos == vec3(-1.0))\
3136 \n {\
3137 \n gl_FragData[1] = vec4(1.0);\
3138 \n }\
3139 \n else\
3140 \n {\
3141 \n vec4 depthValue = in_projectionMatrix * in_modelViewMatrix *\
3142 \n in_volumeMatrix[0] * in_textureDatasetMatrix[0] *\
3143 \n vec4(l_opaqueFragPos, 1.0);\
3144 \n depthValue /= depthValue.w;\
3145 \n gl_FragData[1] = vec4(vec3(0.5 * (gl_DepthRange.far -\
3146 \n gl_DepthRange.near) * depthValue.z + 0.5 *\
3147 \n (gl_DepthRange.far + gl_DepthRange.near)), 1.0);\
3148 \n }");
3149}
3150
3151//--------------------------------------------------------------------------
3153 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3154{
3155 return std::string("\
3156 \n vec3 l_isoPos = g_dataPos;");
3157}
3158
3159//--------------------------------------------------------------------------
3161 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3162{
3163 return std::string("\
3164 \n if(!g_skip && g_srcColor.a > 0.0)\
3165 \n {\
3166 \n l_isoPos = g_dataPos;\
3167 \n g_exit = true; g_skip = true;\
3168 \n }");
3169}
3170
3171//--------------------------------------------------------------------------
3173 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3174{
3175 return std::string("\
3176 \n vec4 depthValue = in_projectionMatrix * in_modelViewMatrix *\
3177 \n in_volumeMatrix[0] * in_textureDatasetMatrix[0] *\
3178 \n vec4(l_isoPos, 1.0);\
3179 \n gl_FragData[0] = vec4(l_isoPos, 1.0);\
3180 \n gl_FragData[1] = vec4(vec3((depthValue.z/depthValue.w) * 0.5 + 0.5),\
3181 \n 1.0);");
3182}
3183
3184//---------------------------------------------------------------------------
3186 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3187{
3188 return std::string("\
3189 \n initializeRayCast();\
3190 \n castRay(-1.0, -1.0);\
3191 \n finalizeRayCast();");
3192}
3193
3194//---------------------------------------------------------------------------
3196 const std::vector<std::string>& varNames, const size_t usedNames)
3197{
3198 std::string shader = "\n";
3199 for (size_t i = 0; i < usedNames; i++)
3200 {
3201 shader += "uniform sampler2D " + varNames[i] + ";\n";
3202 }
3203 return shader;
3204}
3205
3206//---------------------------------------------------------------------------
3208 const std::vector<std::string>& varNames, const size_t usedNames)
3209{
3210 std::string shader = "\n";
3211 for (size_t i = 0; i < usedNames; i++)
3212 {
3213 std::stringstream ss;
3214 ss << i;
3215 shader += " gl_FragData[" + ss.str() + "] = texture2D(" + varNames[i] + ", texCoord);\n";
3216 }
3217 shader += " return;\n";
3218 return shader;
3219}
3220}
3221
3222#endif // vtkVolumeShaderComposer_h
3223// VTK-HeaderTest-Exclude: vtkVolumeShaderComposer.h
virtual vtkPlaneCollection * GetClippingPlanes()
Get/Set the vtkPlaneCollection which specifies the clipping planes.
virtual vtkTypeBool GetParallelProjection()
Set/Get the value of the ParallelProjection instance variable.
static vtkDataSet * SafeDownCast(vtkObjectBase *o)
vtkUnsignedCharArray * GetCellGhostArray()
Get the array that defines the ghost type of each cell.
vtkUnsignedCharArray * GetPointGhostArray()
Gets the array that defines the ghost type of each point.
virtual vtkTypeBool GetUseDepthPass()
If UseDepthPass is on, the mapper will use two passes.
virtual vtkTypeBool GetUseJittering()
If UseJittering is on, each ray traversal direction will be perturbed slightly using a noise-texture ...
static vtkGPUVolumeRayCastMapper * SafeDownCast(vtkObjectBase *o)
topologically and geometrically regular array of data
Definition: vtkImageData.h:157
abstract interface for implicit functions
virtual vtkTypeBool IsA(const char *type)
Return 1 if this class is the same type of (or a subclass of) the named class.
OpenGL implementation of volume rendering through ray-casting.
static vtkOpenGLGPUVolumeRayCastMapper * SafeDownCast(vtkObjectBase *o)
std::map< int, vtkVolumeInputHelper > VolumeInputMap
static vtkRectilinearGrid * SafeDownCast(vtkObjectBase *o)
abstract specification for renderers
Definition: vtkRenderer.h:173
vtkCamera * GetActiveCamera()
Get the current camera.
Abstract class for a volume mapper.
virtual vtkDataSet * GetInput()
Set/Get the input data.
virtual vtkTypeBool GetCropping()
Turn On/Off orthogonal cropping.
virtual int GetBlendMode()
Set/Get the blend mode.
represents the common properties for rendering a volume.
virtual int GetDisableGradientOpacity(int index)
Enable/Disable the gradient opacity function for the given component.
virtual int GetUseClippedVoxelIntensity()
Set/Get whether to use a fixed intensity value for voxels in the clipped space for gradient calculati...
bool HasGradientOpacity(int index=0)
Check whether or not we have the gradient opacity.
int GetShade(int index)
Set/Get the shading of a volume.
virtual int GetTransferFunctionMode()
Color-opacity transfer function mode.
Creates and manages the volume texture rendered by vtkOpenGLGPUVolumeRayCastMapper.
represents a volume (data & properties) in a rendered scene
Definition: vtkVolume.h:134
virtual vtkVolumeProperty * GetProperty()
Set/Get the volume property.
@ string
Definition: vtkX3D.h:496
std::string ClippingDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string ComputeGradientOpacity1DDecl(vtkVolume *vol, int noOfComponents, int independentComponents, std::map< int, std::string > gradientTableMap)
std::string WorkerImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string TerminationExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ClippingDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string TerminationImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ComputeLightingMultiDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents, int vtkNotUsed(numberOfLights), int lightingComplexity)
std::string BinaryMaskDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeTexture *mask, int vtkNotUsed(maskType))
std::string PickingIdLow24PassExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ComputeLightingDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents, int vtkNotUsed(numberOfLights), int lightingComplexity)
std::string CroppingDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string ComputeColorDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, std::map< int, std::string > colorTableMap)
std::string CroppingImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string ShadingExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents=0)
std::string BaseExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ImageSampleDeclarationFrag(const std::vector< std::string > &varNames, const size_t usedNames)
std::string ComputeOpacityMultiDeclaration(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string BaseDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), bool multipleInputs)
std::string ComputeTextureCoordinates(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string DepthPassInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string TerminationInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vol)
std::string RenderToImageInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ComputeClipPositionImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string RenderToImageImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ComputeOpacityDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, std::map< int, std::string > opacityTableMap)
std::string PreComputeGradientsImpl(vtkRenderer *vtkNotUsed(ren), vtkVolume *vtkNotUsed(vol), int noOfComponents=1, int independentComponents=0)
std::string ClippingExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ComputeGradientDeclaration(vtkOpenGLGPUVolumeRayCastMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string BaseInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int lightingComplexity)
std::string PickingIdHigh24PassExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string TerminationDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string PickingActorPassExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string RenderToImageDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string BaseImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string RenderToImageExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ShadingDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ShadingSingleInput(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType, int noOfComponents, int independentComponents=0)
std::string ShadingMultipleInputs(vtkVolumeMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string CompositeMaskDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType)
std::string ComputeRayDirectionDeclaration(vtkRenderer *ren, vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int vtkNotUsed(noOfComponents))
std::string DepthPassImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string GradientCacheDec(vtkRenderer *vtkNotUsed(ren), vtkVolume *vtkNotUsed(vol), vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int independentComponents=0)
std::string Transfer2DDeclaration(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string ClippingImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string CroppingDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ComputeColorMultiDeclaration(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, bool useGradientTF)
std::string CroppingInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string CompositeMaskImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType, int noOfComponents)
std::string ComputeColor2DYAxisDeclaration(int noOfComponents, int vtkNotUsed(independentComponents), std::map< int, std::string > colorTableMap)
std::string ImageSampleImplementationFrag(const std::vector< std::string > &varNames, const size_t usedNames)
std::string CroppingExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ClippingInit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string TerminationDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ShadingDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string PickingActorPassDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ShadingInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string BinaryMaskImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType)
std::string DepthPassExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ComputeOpacity2DDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, std::map< int, std::string > opacityTableMap, int useGradient)
std::string ComputeColor2DDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, std::map< int, std::string > colorTableMap, int useGradient)
std::string ComputeGradientOpacityMulti1DDecl(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string BaseDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int vtkNotUsed(numberOfLights), int lightingComplexity, int noOfComponents, int independentComponents)