VTK  9.2.6
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//--------------------------------------------------------------------------
121std::string BaseDeclarationVertex(vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper,
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//--------------------------------------------------------------------------
151std::string BaseDeclarationFragment(vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper,
152 vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs, int totalNumberOfLights,
153 int numberPositionalLights, bool defaultLighting, 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 if (glMapper->GetVolumetricScatteringBlending() > 0.0)
229 {
230
231 toShaderStr << "mat4 g_eyeToTexture = in_inverseTextureDatasetMatrix[0] *"
232 " in_inverseVolumeMatrix[0] * in_inverseModelViewMatrix;\n";
233 }
234
235 if (inputs[0].Volume->GetProperty() && inputs[0].Volume->GetProperty()->GetShade() &&
236 !defaultLighting && totalNumberOfLights > 0)
237 {
238 toShaderStr << "mat4 g_texToView = in_modelViewMatrix * in_volumeMatrix[0] *"
239 "in_textureDatasetMatrix[0];\n";
240 }
241
242 toShaderStr << "uniform vec2 in_scalarsRange[" << numInputs * 4
243 << "];\n"
244 "uniform vec3 in_cellSpacing["
245 << numInputs
246 << "];\n"
247 "\n"
248 "// Sample distance\n"
249 "uniform float in_sampleDistance;\n"
250 "\n"
251 "// Scales\n"
252 "uniform vec2 in_windowLowerLeftCorner;\n"
253 "uniform vec2 in_inverseOriginalWindowSize;\n"
254 "uniform vec2 in_inverseWindowSize;\n"
255 "uniform vec3 in_textureExtentsMax;\n"
256 "uniform vec3 in_textureExtentsMin;\n"
257 "\n"
258 "// Material and lighting\n"
259 "uniform vec3 in_diffuse[4];\n"
260 "uniform vec3 in_ambient[4];\n"
261 "uniform vec3 in_specular[4];\n"
262 "uniform float in_shininess[4];\n"
263 "\n"
264 "// Others\n"
265 "vec3 g_rayJitter = vec3(0.0);\n"
266 "\n"
267 "uniform vec2 in_averageIPRange;\n";
268
269 toShaderStr << "vec4 g_eyePosObjs[" << numInputs << "];\n";
270
271 const bool hasGradientOpacity = HasGradientOpacity(inputs);
272 if (totalNumberOfLights > 0 || hasGradientOpacity)
273 {
274 toShaderStr << "uniform bool in_twoSidedLighting;\n";
275 }
276
277 if (glMapper->GetVolumetricScatteringBlending() > 0.0)
278 {
279 toShaderStr << R"***(
280uniform float in_giReach;
281uniform float in_anisotropy;
282uniform float in_volumetricScatteringBlending;
283
284)***";
285 }
286
287 if (totalNumberOfLights > 0)
288 {
289 std::string totalLights = std::to_string(totalNumberOfLights);
290 std::string positionalLights = std::to_string(numberPositionalLights);
291
292 if (!defaultLighting)
293 {
294 toShaderStr << "#define TOTAL_NUMBER_LIGHTS " << totalLights
295 << "\n"
296 "#define NUMBER_POS_LIGHTS "
297 << positionalLights
298 << "\n"
299 "vec4 g_fragWorldPos;\n"
300 "uniform vec3 in_lightAmbientColor[TOTAL_NUMBER_LIGHTS];\n"
301 "uniform vec3 in_lightDiffuseColor[TOTAL_NUMBER_LIGHTS];\n"
302 "uniform vec3 in_lightSpecularColor[TOTAL_NUMBER_LIGHTS];\n"
303 "uniform vec3 in_lightDirection[TOTAL_NUMBER_LIGHTS];\n";
304 if (numberPositionalLights > 0)
305 {
306 toShaderStr << "uniform vec3 in_lightPosition[NUMBER_POS_LIGHTS];\n"
307 "uniform vec3 in_lightAttenuation[NUMBER_POS_LIGHTS];\n"
308 "uniform float in_lightConeAngle[NUMBER_POS_LIGHTS];\n"
309 "uniform float in_lightExponent[NUMBER_POS_LIGHTS];\n";
310 }
311
312 if (glMapper->GetVolumetricScatteringBlending() > 0.0)
313 {
314 toShaderStr << "vec3 g_lightDirectionTex[TOTAL_NUMBER_LIGHTS];";
315
316 if (numberPositionalLights > 0)
317 {
318 toShaderStr << "vec3 g_lightPositionTex[NUMBER_POS_LIGHTS];";
319 }
320 }
321 }
322 else
323 {
324 toShaderStr << "uniform vec3 in_lightAmbientColor[1];\n"
325 "uniform vec3 in_lightDiffuseColor[1];\n"
326 "uniform vec3 in_lightSpecularColor[1];\n"
327 "vec4 g_lightPosObj["
328 << numInputs
329 << "];\n"
330 "vec3 g_ldir["
331 << numInputs
332 << "];\n"
333 "vec3 g_vdir["
334 << numInputs
335 << "];\n"
336 "vec3 g_h["
337 << numInputs << "];\n";
338 }
339 }
340
341 if (noOfComponents > 1 && independentComponents)
342 {
343 toShaderStr << "uniform vec4 in_componentWeight;\n";
344 }
345
347 glMapper->GetUseDepthPass())
348 {
349 toShaderStr << "uniform sampler2D in_depthPassSampler;\n";
350 }
351
353 {
354 toShaderStr << "#if NUMBER_OF_CONTOURS\n"
355 "uniform float in_isosurfacesValues[NUMBER_OF_CONTOURS];\n"
356 "\n"
357 "int findIsoSurfaceIndex(float scalar, float array[NUMBER_OF_CONTOURS+2])\n"
358 "{\n"
359 " int index = NUMBER_OF_CONTOURS >> 1;\n"
360 " while (scalar > array[index]) ++index;\n"
361 " while (scalar < array[index]) --index;\n"
362 " return index;\n"
363 "}\n"
364 "#endif\n";
365 }
366 else if (glMapper->GetBlendMode() == vtkVolumeMapper::SLICE_BLEND)
367 {
368 vtkVolume* vol = inputs.begin()->second.Volume;
369 vtkImplicitFunction* func = vol->GetProperty()->GetSliceFunction();
370
371 if (func && func->IsA("vtkPlane"))
372 {
373 toShaderStr
374 << "uniform vec3 in_slicePlaneOrigin;\n"
375 "uniform vec3 in_slicePlaneNormal;\n"
376 "vec3 g_intersection;\n"
377 "\n"
378 "float intersectRayPlane(vec3 rayOrigin, vec3 rayDir)\n"
379 "{\n"
380 " vec4 planeNormal = in_inverseVolumeMatrix[0] * vec4(in_slicePlaneNormal, 0.0);\n"
381 " float denom = dot(planeNormal.xyz, rayDir);\n"
382 " if (abs(denom) > 1e-6)\n"
383 " {\n"
384 " vec4 planeOrigin = in_inverseVolumeMatrix[0] * vec4(in_slicePlaneOrigin, 1.0);\n"
385 " return dot(planeOrigin.xyz - rayOrigin, planeNormal.xyz) / denom;\n"
386 " }\n"
387 " return -1.0;\n"
388 "}\n";
389 }
390 }
392 return toShaderStr.str();
393}
394
395//--------------------------------------------------------------------------
396std::string BaseInit(vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper,
397 vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs, bool defaultLighting)
398{
400 vtkVolume* vol = inputs.begin()->second.Volume;
401 const int numInputs = static_cast<int>(inputs.size());
402
403 std::ostringstream shaderStr;
406 {
407 shaderStr << "\
408 \n //\
409 \n vec2 fragTexCoord2 = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
410 \n in_inverseWindowSize;\
411 \n vec4 depthValue = texture2D(in_depthPassSampler, fragTexCoord2);\
412 \n vec4 rayOrigin = WindowToNDC(gl_FragCoord.x, gl_FragCoord.y, depthValue.x);\
413 \n\
414 \n // From normalized device coordinates to eye coordinates.\
415 \n // in_projectionMatrix is inversed because of way VT\
416 \n // From eye coordinates to texture coordinates\
417 \n rayOrigin = in_inverseTextureDatasetMatrix[0] *\
418 \n in_inverseVolumeMatrix[0] *\
419 \n in_inverseModelViewMatrix *\
420 \n in_inverseProjectionMatrix *\
421 \n rayOrigin;\
422 \n rayOrigin /= rayOrigin.w;\
423 \n g_rayOrigin = rayOrigin.xyz;";
424 }
425 else
426 {
427 shaderStr << "\
428 \n // Get the 3D texture coordinates for lookup into the in_volume dataset\
429 \n g_rayOrigin = ip_textureCoords.xyz;";
430 }
431
432 shaderStr << "\
433 \n\
434 \n // Eye position in dataset space\
435 \n g_eyePosObj = in_inverseVolumeMatrix[0] * vec4(in_cameraPos, 1.0);";
436 for (int i = 0; i < numInputs; ++i)
437 {
438 // In multi-volume case the first volume matrix is of the bounding box
439 shaderStr << "\
440 \n g_eyePosObjs["
441 << i << "] = in_inverseVolumeMatrix[" << (numInputs > 1 ? i + 1 : i)
442 << "] * vec4(in_cameraPos, 1.0);";
443 }
444 shaderStr << "\n\
445 \n // Getting the ray marching direction (in dataset space)\
446 \n vec3 rayDir = computeRayDirection();\
447 \n\
448 \n // 2D Texture fragment coordinates [0,1] from fragment coordinates.\
449 \n // The frame buffer texture has the size of the plain buffer but \
450 \n // we use a fraction of it. The texture coordinate is less than 1 if\
451 \n // the reduction factor is less than 1.\
452 \n // Device coordinates are between -1 and 1. We need texture\
453 \n // coordinates between 0 and 1. The in_depthSampler\
454 \n // buffer has the original size buffer.\
455 \n vec2 fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
456 \n in_inverseWindowSize;\
457 \n\
458 \n // Multiply the raymarching direction with the step size to get the\
459 \n // sub-step size we need to take at each raymarching step\
460 \n g_dirStep = (ip_inverseTextureDataAdjusted *\
461 \n vec4(rayDir, 0.0)).xyz * in_sampleDistance;\
462 \n g_lengthStep = length(g_dirStep);\
463 \n";
464
465 shaderStr << "\
466 \n float jitterValue = 0.0;\
467 \n";
468
470 {
471 // Intersection is computed with g_rayOrigin, so we should not modify it with Slice mode
472 if (glMapper->GetUseJittering())
473 {
474 shaderStr << "\
475 \n jitterValue = texture2D(in_noiseSampler, gl_FragCoord.xy /\
476 vec2(textureSize(in_noiseSampler, 0))).x;\
477 \n g_rayJitter = g_dirStep * jitterValue;\
478 \n";
479 }
480 else
481 {
482 shaderStr << "\
483 \n g_rayJitter = g_dirStep;\
484 \n";
485 }
486 shaderStr << "\
487 \n g_rayOrigin += g_rayJitter;\
488 \n";
489 }
490
491 shaderStr << "\
492 \n // Flag to determine if voxel should be considered for the rendering\
493 \n g_skip = false;";
494
495 if (vol->GetProperty()->GetShade() && defaultLighting)
496 {
497 shaderStr << "\
498 \n // Light position in dataset space";
499 for (int i = 0; i < numInputs; ++i)
500 {
501 // In multi-volume case the first volume matrix is of the bounding box
502 shaderStr << "\
503 \n g_lightPosObj["
504 << i << "] = (in_inverseVolumeMatrix[" << (numInputs > 1 ? i + 1 : i) << "] *\
505 \n vec4(in_cameraPos, 1.0));\
506 \n g_ldir["
507 << i << "] = normalize(g_lightPosObj[" << i << "].xyz - ip_vertexPos);\
508 \n g_vdir["
509 << i << "] = normalize(g_eyePosObjs[" << i << "].xyz - ip_vertexPos);\
510 \n g_h["
511 << i << "] = normalize(g_ldir[" << i << "] + g_vdir[" << i << "]);";
512 }
513 }
515 return shaderStr.str();
516}
517
518//--------------------------------------------------------------------------
519std::string BaseImplementation(
520 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
521{
523
524 std::string str("\
525 \n g_skip = false;");
526
527 // Blanking support
529 bool blankCells = (dataSet->GetCellGhostArray() != nullptr);
530 bool blankPoints = (dataSet->GetPointGhostArray() != nullptr);
531 if (blankPoints || blankCells)
532 {
533 str += std::string("\
534 \n // Check whether the neighboring points/cells are blank.\
535 \n // Note the half cellStep because texels are point centered.\
536 \n vec3 xvec = vec3(in_cellStep[0].x/2.0, 0.0, 0.0);\
537 \n vec3 yvec = vec3(0.0, in_cellStep[0].y/2.0, 0.0);\
538 \n vec3 zvec = vec3(0.0, 0.0, in_cellStep[0].z/2.0);\
539 \n vec3 texPosPVec[3];\
540 \n texPosPVec[0] = g_dataPos + xvec;\
541 \n texPosPVec[1] = g_dataPos + yvec;\
542 \n texPosPVec[2] = g_dataPos + zvec;\
543 \n vec3 texPosNVec[3];\
544 \n texPosNVec[0] = g_dataPos - xvec;\
545 \n texPosNVec[1] = g_dataPos - yvec;\
546 \n texPosNVec[2] = g_dataPos - zvec;\
547 \n vec4 blankValue = texture3D(in_blanking, g_dataPos);\
548 \n vec4 blankValueXP = texture3D(in_blanking, texPosPVec[0]);\
549 \n vec4 blankValueYP = texture3D(in_blanking, texPosPVec[1]);\
550 \n vec4 blankValueZP = texture3D(in_blanking, texPosPVec[2]);\
551 \n vec4 blankValueXN = texture3D(in_blanking, texPosNVec[0]);\
552 \n vec4 blankValueYN = texture3D(in_blanking, texPosNVec[1]);\
553 \n vec4 blankValueZN = texture3D(in_blanking, texPosNVec[2]);\
554 \n vec3 blankValuePx;\
555 \n blankValuePx[0] = blankValueXP.x;\
556 \n blankValuePx[1] = blankValueYP.x;\
557 \n blankValuePx[2] = blankValueZP.x;\
558 \n vec3 blankValuePy;\
559 \n blankValuePy[0] = blankValueXP.y;\
560 \n blankValuePy[1] = blankValueYP.y;\
561 \n blankValuePy[2] = blankValueZP.y;\
562 \n vec3 blankValueNx;\
563 \n blankValueNx[0] = blankValueXN.x;\
564 \n blankValueNx[1] = blankValueYN.x;\
565 \n blankValueNx[2] = blankValueZN.x;\
566 \n vec3 blankValueNy;\
567 \n blankValueNy[0] = blankValueXN.y;\
568 \n blankValueNy[1] = blankValueYN.y;\
569 \n blankValueNy[2] = blankValueZN.y;\
570 \n");
571 if (blankPoints)
572 {
573 str += std::string("\
574 \n // If the current or neighboring points\
575 \n // (that belong to cells that share this texel) are blanked,\
576 \n // skip the texel. In other words, if point 1 were blank,\
577 \n // texels 0, 1 and 2 would have to be skipped.\
578 \n if (blankValue.x > 0.0 ||\
579 \n any(greaterThan(blankValueNx, vec3(0.0))) ||\
580 \n any(greaterThan(blankValuePx, vec3(0.0))))\
581 \n {\
582 \n // skip this texel\
583 \n g_skip = true;\
584 \n }\
585 \n");
586 if (blankCells)
587 {
588 str += std::string("\
589 \n // If the current or previous cells (that share this texel)\
590 \n // are blanked, skip the texel. In other words, if cell 1\
591 \n // is blanked, texels 1 and 2 would have to be skipped.\
592 \n else if (blankValue.y > 0.0 ||\
593 \n any(greaterThan(blankValuePy, vec3(0.0))) ||\
594 \n any(greaterThan(blankValueNy, vec3(0.0))))\
595 \n {\
596 \n // skip this texel\
597 \n g_skip = true;\
598 \n }\
599 \n");
600 }
601 }
602 else if (blankCells)
603 {
604 str += std::string("\
605 \n // If the current or previous cells (that share this texel)\
606 \n // are blanked, skip the texel. In other words, if cell 1\
607 \n // is blanked, texels 1 and 2 would have to be skipped.\
608 \n if (blankValue.x > 0.0 ||\
609 \n any(greaterThan(blankValueNx, vec3(0.0))) ||\
610 \n any(greaterThan(blankValuePx, vec3(0.0))))\
611 \n {\
612 \n // skip this texel\
613 \n g_skip = true;\
614 \n }\
615 \n");
616 }
617 }
618
620 {
621 str += std::string("\
622 \n g_dataPos = g_intersection;\
623 \n");
624 }
626 return str;
627}
628
629//--------------------------------------------------------------------------
630std::string BaseExit(
631 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
633 return std::string();
634}
635
636//--------------------------------------------------------------------------
637std::string ComputeGradientOpacity1DDecl(vtkVolume* vol, int noOfComponents,
638 int independentComponents, std::map<int, std::string> gradientTableMap)
639{
640 auto volProperty = vol->GetProperty();
641 std::ostringstream ss;
642 if (volProperty->HasGradientOpacity())
643 {
644 ss << "uniform sampler2D " << ArrayBaseName(gradientTableMap[0]) << "[" << noOfComponents
645 << "];\n";
646 }
647 bool useLabelGradientOpacity =
648 (volProperty->HasLabelGradientOpacity() && (noOfComponents == 1 || !independentComponents));
649 if (useLabelGradientOpacity)
650 {
651 ss << "uniform sampler2D in_labelMapGradientOpacity;\n";
652 }
653
654 std::string shaderStr = ss.str();
655
656 if (volProperty->HasGradientOpacity() && noOfComponents > 0)
657 {
658 if (noOfComponents == 1 || !independentComponents)
659 {
660 shaderStr += std::string("\
661 \nfloat computeGradientOpacity(vec4 grad)\
662 \n {\
663 \n return texture2D(" +
664 gradientTableMap[0] + ", vec2(grad.w, 0.0)).r;\
665 \n }");
666 }
667 else
668 {
669 shaderStr += std::string("\
670 \nfloat computeGradientOpacity(vec4 grad, int component)\
671 \n {");
672
673 for (int i = 0; i < noOfComponents; ++i)
674 {
675 std::ostringstream toString;
676 toString << i;
677 shaderStr += std::string("\
678 \n if (component == " +
679 toString.str() + ")");
680
681 shaderStr += std::string("\
682 \n {\
683 \n return texture2D(" +
684 gradientTableMap[i] + ", vec2(grad.w, 0.0)).r;\
685 \n }");
686 }
687
688 shaderStr += std::string("\
689 \n }");
690 }
691 }
692
693 if (useLabelGradientOpacity)
694 {
695 shaderStr += std::string("\
696 \nfloat computeGradientOpacityForLabel(vec4 grad, float label)\
697 \n {\
698 \n return texture2D(in_labelMapGradientOpacity, vec2(grad.w, label)).r;\
699 \n }");
700 }
702 return shaderStr;
703}
704
705//--------------------------------------------------------------------------
708{
709 const bool hasLighting = HasLighting(inputs);
710 const bool hasGradientOp = HasGradientOpacity(inputs);
711
712 std::string shaderStr;
713 if (hasLighting || hasGradientOp)
714 {
715 shaderStr += std::string(
716 "// c is short for component\n"
717 "vec4 computeGradient(in vec3 texPos, in int c, in sampler3D volume,in int index)\n"
718 "{\n"
719 " // Approximate Nabla(F) derivatives with central differences.\n"
720 " vec3 g1; // F_front\n"
721 " vec3 g2; // F_back\n"
722 " vec3 xvec = vec3(in_cellStep[index].x, 0.0, 0.0);\n"
723 " vec3 yvec = vec3(0.0, in_cellStep[index].y, 0.0);\n"
724 " vec3 zvec = vec3(0.0, 0.0, in_cellStep[index].z);\n"
725 " vec3 texPosPvec[3];\n"
726 " texPosPvec[0] = texPos + xvec;\n"
727 " texPosPvec[1] = texPos + yvec;\n"
728 " texPosPvec[2] = texPos + zvec;\n"
729 " vec3 texPosNvec[3];\n"
730 " texPosNvec[0] = texPos - xvec;\n"
731 " texPosNvec[1] = texPos - yvec;\n"
732 " texPosNvec[2] = texPos - zvec;\n"
733 " g1.x = texture3D(volume, vec3(texPosPvec[0]))[c];\n"
734 " g1.y = texture3D(volume, vec3(texPosPvec[1]))[c];\n"
735 " g1.z = texture3D(volume, vec3(texPosPvec[2]))[c];\n"
736 " g2.x = texture3D(volume, vec3(texPosNvec[0]))[c];\n"
737 " g2.y = texture3D(volume, vec3(texPosNvec[1]))[c];\n"
738 " g2.z = texture3D(volume, vec3(texPosNvec[2]))[c];\n"
739 "\n");
740 if (UseClippedVoxelIntensity(inputs) && mapper->GetClippingPlanes())
741 {
742 shaderStr +=
743 std::string(" vec4 g1ObjDataPos[3], g2ObjDataPos[3];\n"
744 " for (int i = 0; i < 3; ++i)\n"
745 " {\n"
746 " g1ObjDataPos[i] = clip_texToObjMat * vec4(texPosPvec[i], 1.0);\n"
747 " if (g1ObjDataPos[i].w != 0.0)\n"
748 " {\n"
749 " g1ObjDataPos[i] /= g1ObjDataPos[i].w;\n"
750 " }\n"
751 " g2ObjDataPos[i] = clip_texToObjMat * vec4(texPosNvec[i], 1.0);\n"
752 " if (g2ObjDataPos[i].w != 0.0)\n"
753 " {\n"
754 " g2ObjDataPos[i] /= g2ObjDataPos[i].w;\n"
755 " }\n"
756 " }\n"
757 "\n"
758 " for (int i = 0; i < clip_numPlanes && !g_skip; i = i + 6)\n"
759 " {\n"
760 " vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\n"
761 " in_clippingPlanes[i + 2],\n"
762 " in_clippingPlanes[i + 3]);\n"
763 " vec3 planeNormal = normalize(vec3(in_clippingPlanes[i + 4],\n"
764 " in_clippingPlanes[i + 5],\n"
765 " in_clippingPlanes[i + 6]));\n"
766 " for (int j = 0; j < 3; ++j)\n"
767 " {\n"
768 " if (dot(vec3(planeOrigin - g1ObjDataPos[j].xyz), planeNormal) > 0)\n"
769 " {\n"
770 " g1[j] = in_clippedVoxelIntensity;\n"
771 " }\n"
772 " if (dot(vec3(planeOrigin - g2ObjDataPos[j].xyz), planeNormal) > 0)\n"
773 " {\n"
774 " g2[j] = in_clippedVoxelIntensity;\n"
775 " }\n"
776 " }\n"
777 " }\n"
778 "\n");
779 }
780 shaderStr += std::string(" // Apply scale and bias to the fetched values.\n"
781 " g1 = g1 * in_volume_scale[index][c] + in_volume_bias[index][c];\n"
782 " g2 = g2 * in_volume_scale[index][c] + in_volume_bias[index][c];\n"
783 "\n");
784 if (!hasGradientOp)
785 {
786 shaderStr +=
787 std::string(" // Central differences: (F_front - F_back) / 2h\n"
788 " // This version of computeGradient() is only used for lighting\n"
789 " // calculations (only direction matters), hence the difference is\n"
790 " // not scaled by 2h and a dummy gradient mag is returned (-1.).\n"
791 " return vec4((g1 - g2) / in_cellSpacing[index], -1.0);\n"
792 "}\n");
793 }
794 else
795 {
796 shaderStr += std::string(
797 " // Scale values the actual scalar range.\n"
798 " float range = in_scalarsRange[4*index+c][1] - in_scalarsRange[4*index+c][0];\n"
799 " g1 = in_scalarsRange[4*index+c][0] + range * g1;\n"
800 " g2 = in_scalarsRange[4*index+c][0] + range * g2;\n"
801 "\n"
802 " // Central differences: (F_front - F_back) / 2h\n"
803 " g2 = g1 - g2;\n"
804 "\n"
805 " float avgSpacing = (in_cellSpacing[index].x +\n"
806 " in_cellSpacing[index].y + in_cellSpacing[index].z) / 3.0;\n"
807 " vec3 aspect = in_cellSpacing[index] * 2.0 / avgSpacing;\n"
808 " g2 /= aspect;\n"
809 " float grad_mag = length(g2);\n"
810 "\n"
811 " // Handle normalizing with grad_mag == 0.0\n"
812 " g2 = grad_mag > 0.0 ? normalize(g2) : vec3(0.0);\n"
813 "\n"
814 " // Since the actual range of the gradient magnitude is unknown,\n"
815 " // assume it is in the range [0, 0.25 * dataRange].\n"
816 " range = range != 0 ? range : 1.0;\n"
817 " grad_mag = grad_mag / (0.25 * range);\n"
818 " grad_mag = clamp(grad_mag, 0.0, 1.0);\n"
819 "\n"
820 " return vec4(g2.xyz, grad_mag);\n"
821 "}\n");
822 }
823 }
824 else
825 {
826 shaderStr += std::string(
827 "vec4 computeGradient(in vec3 texPos, in int c, in sampler3D volume, in int index)\n"
828 "{\n"
829 " return vec4(0.0);\n"
830 "}\n");
831 }
833 return shaderStr;
834}
835
836//---------------------------------------------------------------------------
837std::string ComputeMatricesInit(
838 vtkOpenGLGPUVolumeRayCastMapper* vtkNotUsed(mapper), int numberPositionalLights)
839{
840 std::string resStr;
841 resStr += R"***(
842 for(int i=0; i<TOTAL_NUMBER_LIGHTS; i++)
843 {
844 g_lightDirectionTex[i] = (g_eyeToTexture * vec4(-in_lightDirection[i], 0.0)).xyz;
845 }
846 )***";
847
848 if (numberPositionalLights > 0)
849 {
850 resStr += R"***(
851 for(int i=0; i<NUMBER_POS_LIGHTS; i++)
852 {
853 g_lightPositionTex[i] = (g_eyeToTexture * vec4(in_lightPosition[i], 1.0)).xyz;
854 }
855 )***";
857 return resStr;
858}
859
860//--------------------------------------------------------------------------
861std::string ComputeRGBA2DWithGradientDeclaration(vtkRenderer* vtkNotUsed(ren),
862 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), int noOfComponents,
863 int independentComponents, std::map<int, std::string> opacityTableMap, int useGradient)
864{
865 std::string resStr;
866 std::string functionBody;
867 bool severalIndpt = noOfComponents > 1 && independentComponents;
868 std::string functionSignature = severalIndpt
869 ? "vec4 computeRGBAWithGrad(vec4 scalar, vec4 grad, int component)\n"
870 : "vec4 computeRGBAWithGrad(vec4 scalar, vec4 grad)\n";
871
872 if (severalIndpt)
873 {
874 // Multiple independent components
875
876 if (!useGradient)
877 {
878 functionBody +=
879 "vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
880 "for (int i = 0; i < 4; ++i)\n"
881 "{\n"
882 " yscalar[i] = yscalar[i] * in_transfer2DYAxis_scale[i] + in_transfer2DYAxis_bias[i];\n"
883 "}\n";
884 }
885
886 for (int i = 0; i < noOfComponents; ++i)
887 {
888 std::string secondAxis(useGradient
889 // we take the same grad for all components so we have to be sure that
890 // the one given as a parameter is computed wrt the right component
891 ? "grad.w"
892 : std::string("yscalar[") + std::to_string(i) + "]");
893
894 functionBody += " if(component == " + std::to_string(i) +
895 ")\n"
896 " {\n"
897 " return texture2D(" +
898 opacityTableMap[i] + ",\n" + " vec2(scalar[" + std::to_string(i) + "], " + secondAxis +
899 "))\n" + " }\n";
900 }
901 }
902
903 else if (noOfComponents == 2 && !independentComponents)
904 {
905 std::string secondAxis(useGradient ? "grad.w" : "yscalar.y");
906
907 functionBody += " return texture2D(" + opacityTableMap[0] +
908 ",\n"
909 " vec2(scalar.y, " +
910 secondAxis + "));\n";
911 }
912
913 else
914 {
915 if (useGradient)
916 {
917 // Dependent components (RGBA) || Single component
918 functionBody += " return texture2D(" + opacityTableMap[0] +
919 ",\n"
920 " vec2(scalar.a, grad.w));\n";
921 }
922 else
923 {
924 // Dependent compoennts (RGBA) || Single component
925 functionBody +=
926 " vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
927 " yscalar.r = yscalar.r * in_transfer2DYAxis_scale.r + in_transfer2DYAxis_bias.r;\n"
928 " yscalar = vec4(yscalar.r);\n"
929 " return texture2D(" +
930 opacityTableMap[0] +
931 ",\n"
932 " vec2(scalar.a, yscalar.w));\n";
933 }
934 }
935
936 resStr = functionSignature + "{\n" + functionBody + "}\n";
938 return resStr;
939}
940
941//-----------------------------------------------------------------------
943 vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs, int noOfComponents,
944 int independentComponents, int useGradYAxis, std::string position, bool requestColor = false)
945{
946 // relies on the declaration of variables opacity, gradient, c, volume, index, scalar, gradTF,
947 // opacityTF, label in the scope
948 std::string resStr;
949
950 if (inputs.size() > 1)
951 {
952 // Multi Volume
953 const bool hasGradOp = ::HasGradientOpacity(inputs);
954 resStr += " opacity = computeOpacity(vec4(scalar), opacityTF);\n";
955 // either all volumes have a TF either none have one, so we can have
956 // the same opacity call for all volumes
957 if (hasGradOp)
958 {
959 resStr += std::string(" gradient = computeGradient(") + position + ", c, volume, index);\n";
960 resStr += " opacity *= computeGradientOpacity(gradient, gradTF);\n";
961 }
962 // ignore request color for now, but given the actual architecture, it should be a
963 // succession of 'if' comparing the volume idx
964 if (requestColor)
965 {
966 vtkGenericWarningMacro(<< "ComputeOpacityEvaluationCall was called with requestColor, but "
967 "MultiVolume does not support this option yet.");
968 }
969 }
970 else
971 {
972 // Single Volume
973 vtkVolumeProperty* volProp = inputs[0].Volume->GetProperty();
974 const bool hasGradOp = volProp->HasGradientOpacity() && !volProp->GetDisableGradientOpacity();
975 const bool useLabelGradientOpacity = (volProp->HasLabelGradientOpacity() &&
976 (noOfComponents == 1 || !independentComponents) && !volProp->GetDisableGradientOpacity());
977
978 const int tfMode = volProp->GetTransferFunctionMode();
979
980 bool indpComps = (noOfComponents > 1 && independentComponents);
981 std::string compArgument = (indpComps) ? std::string(", c") : std::string();
982
983 const bool needGrad = (tfMode == vtkVolumeProperty::TF_2D && useGradYAxis); // to be sure
984
985 if (tfMode == vtkVolumeProperty::TF_1D)
986 {
987
988 std::string compWeights = indpComps ? std::string(" * in_componentWeight[c]") : std::string();
989
990 resStr += std::string(" opacity = computeOpacity(vec4(scalar)") + compArgument +
991 std::string(")") + compWeights + ";\n";
992
993 if (hasGradOp || useLabelGradientOpacity)
994 {
995 resStr += std::string(" gradient = computeGradient(") + position +
996 std::string(", c, volume, index);\n"
997 " if(gradient.w >= 0.0) {\n") +
998 (hasGradOp ? (std::string(" opacity *= computeGradientOpacity(gradient") +
999 compArgument + ")" + compWeights + ";\n")
1000 : std::string())
1001
1002 + (useLabelGradientOpacity
1003 ? (std::string(" opacity *= computeGradientOpacityForLabel(gradient, label);\n"))
1004 : std::string())
1005
1006 + std::string(" }\n");
1007 }
1008
1009 if (requestColor)
1010 {
1011 resStr +=
1012 " color = texture2D(" + inputs[0].RGBTablesMap[0] + ", vec2(scalar, 0.0)).xyz;\n";
1013 }
1014 }
1015 else
1016 {
1017 // 2D TF
1018 if (needGrad)
1019 {
1020 resStr +=
1021 std::string(" gradient = computeGradient(") + position + ", c, volume, index);\n";
1022 }
1023 resStr += std::string(" vec4 lutRes = computeRGBAWithGrad(vec4(scalar), gradient") +
1024 compArgument + std::string(");\n");
1025
1026 resStr += " opacity = lutRes.a;\n";
1027
1028 if (requestColor)
1029 {
1030 resStr += " color = lutRes.xyz\n";
1031 }
1032 }
1033 }
1035 return resStr;
1036}
1037
1038//--------------------------------------------------------------------------
1040 vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs, int noOfComponents,
1041 int independentComponents, int useGradYAxis)
1042{
1043 const bool hasLighting = ::HasLighting(inputs);
1044 const bool hasGradientOp = ::HasGradientOpacity(inputs);
1045
1046 std::string functionSignature;
1047
1048 if (inputs.size() > 1)
1049 {
1050 if (hasGradientOp)
1051 {
1052 functionSignature = std::string(
1053 "vec4 computeDensityGradient(in vec3 texPos, in int c, in sampler3D volume, "
1054 "const in sampler2D opacityTF, const in sampler2D gradTF, in int index, float label)\n");
1055 }
1056 else
1057 {
1058 functionSignature =
1059 std::string("vec4 computeDensityGradient(in vec3 texPos, in int c, in sampler3D volume, "
1060 "const in sampler2D opacityTF, in int index, float label)\n");
1061 }
1062 }
1063 else
1064 {
1065 functionSignature = std::string("vec4 computeDensityGradient(in vec3 texPos, in int c, in "
1066 "sampler3D volume, in int index, float label)\n");
1067 }
1068
1069 std::string shaderStr;
1070 if (hasLighting || hasGradientOp)
1071 {
1072
1073 std::string opacityTFcall;
1074 std::string gradComput;
1075 // this table remembers the correspondence results <-> texture coordinates
1076 static const std::array<std::pair<const char*, const char*>, 6> results_texPos = { {
1077 { " g1.x", "texPosPvec[0]" },
1078 { " g1.y", "texPosPvec[1]" },
1079 { " g1.z", "texPosPvec[2]" },
1080 { " g2.x", "texPosNvec[0]" },
1081 { " g2.y", "texPosNvec[1]" },
1082 { " g2.z", "texPosNvec[2]" },
1083 } };
1084
1085 shaderStr += std::string("// c is short for component\n") + functionSignature +
1086 std::string("{\n"
1087 " // Approximate Nabla(F) derivatives with central differences.\n"
1088 " vec3 g1; // F_front\n"
1089 " vec3 g2; // F_back\n"
1090 " vec3 xvec = vec3(in_cellStep[index].x, 0.0, 0.0);\n"
1091 " vec3 yvec = vec3(0.0, in_cellStep[index].y, 0.0);\n"
1092 " vec3 zvec = vec3(0.0, 0.0, in_cellStep[index].z);\n"
1093 " vec3 texPosPvec[3];\n"
1094 " texPosPvec[0] = texPos + xvec;\n"
1095 " texPosPvec[1] = texPos + yvec;\n"
1096 " texPosPvec[2] = texPos + zvec;\n"
1097 " vec3 texPosNvec[3];\n"
1098 " texPosNvec[0] = texPos - xvec;\n"
1099 " texPosNvec[1] = texPos - yvec;\n"
1100 " texPosNvec[2] = texPos - zvec;\n"
1101 " float scalar;\n"
1102 " float opacity;\n"
1103 " vec4 gradient;\n"
1104 "\n");
1105
1106 for (auto& gradComp : results_texPos)
1107 {
1108 // opacityTFcall corresponds to code snippet used to compute the opacity
1109 opacityTFcall = ComputeOpacityEvaluationCall(
1110 mapper, inputs, noOfComponents, independentComponents, useGradYAxis, gradComp.second);
1111 shaderStr += std::string(" scalar = texture3D(volume,") + gradComp.second +
1112 std::string(")[c];\n"
1113 " scalar = scalar * in_volume_scale[index][c] + in_volume_bias[index][c];\n") +
1114 opacityTFcall + gradComp.first + " = opacity;\n";
1115 }
1116
1117 if (::UseClippedVoxelIntensity(inputs) && mapper->GetClippingPlanes())
1118 {
1119 shaderStr +=
1120 std::string(" vec4 g1ObjDataPos[3], g2ObjDataPos[3];\n"
1121 " for (int i = 0; i < 3; ++i)\n"
1122 " {\n"
1123 " g1ObjDataPos[i] = clip_texToObjMat * vec4(texPosPvec[i], 1.0);\n"
1124 " if (g1ObjDataPos[i].w != 0.0)\n"
1125 " {\n"
1126 " g1ObjDataPos[i] /= g1ObjDataPos[i].w;\n"
1127 " }\n"
1128 " g2ObjDataPos[i] = clip_texToObjMat * vec4(texPosNvec[i], 1.0);\n"
1129 " if (g2ObjDataPos[i].w != 0.0)\n"
1130 " {\n"
1131 " g2ObjDataPos[i] /= g2ObjDataPos[i].w;\n"
1132 " }\n"
1133 " }\n"
1134 "\n"
1135 " for (int i = 0; i < clip_numPlanes && !g_skip; i = i + 6)\n"
1136 " {\n"
1137 " vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\n"
1138 " in_clippingPlanes[i + 2],\n"
1139 " in_clippingPlanes[i + 3]);\n"
1140 " vec3 planeNormal = normalize(vec3(in_clippingPlanes[i + 4],\n"
1141 " in_clippingPlanes[i + 5],\n"
1142 " in_clippingPlanes[i + 6]));\n"
1143 " for (int j = 0; j < 3; ++j)\n"
1144 " {\n"
1145 " if (dot(vec3(planeOrigin - g1ObjDataPos[j].xyz), planeNormal) > 0)\n"
1146 " {\n"
1147 " g1[j] = in_clippedVoxelIntensity;\n"
1148 " }\n"
1149 " if (dot(vec3(planeOrigin - g2ObjDataPos[j].xyz), planeNormal) > 0)\n"
1150 " {\n"
1151 " g2[j] = in_clippedVoxelIntensity;\n"
1152 " }\n"
1153 " }\n"
1154 " }\n"
1155 "\n");
1156 }
1157
1158 if (!hasGradientOp)
1159 {
1160 shaderStr +=
1161 std::string(" // Central differences: (F_front - F_back) / 2h\n"
1162 " // This version of computeGradient() is only used for lighting\n"
1163 " // calculations (only direction matters), hence the difference is\n"
1164 " // not scaled by 2h and a dummy gradient mag is returned (-1.).\n"
1165 " return vec4((g1 - g2) / in_cellSpacing[index], -1.0);\n"
1166 "}\n");
1167 }
1168 else
1169 {
1170 shaderStr += std::string(
1171 " // Scale values the actual scalar range.\n"
1172 " float range = in_scalarsRange[4*index+c][1] - in_scalarsRange[4*index+c][0];\n"
1173 " g1 = in_scalarsRange[4*index+c][0] + range * g1;\n"
1174 " g2 = in_scalarsRange[4*index+c][0] + range * g2;\n"
1175 "\n"
1176 " // Central differences: (F_front - F_back) / 2h\n"
1177 " g2 = g1 - g2;\n"
1178 "\n"
1179 " float avgSpacing = (in_cellSpacing[index].x +\n"
1180 " in_cellSpacing[index].y + in_cellSpacing[index].z) / 3.0;\n"
1181 " vec3 aspect = in_cellSpacing[index] * 2.0 / avgSpacing;\n"
1182 " g2 /= aspect;\n"
1183 " float grad_mag = length(g2);\n"
1184 "\n"
1185 " // Handle normalizing with grad_mag == 0.0\n"
1186 " g2 = grad_mag > 0.0 ? normalize(g2) : vec3(0.0);\n"
1187 "\n"
1188 " // Since the actual range of the gradient magnitude is unknown,\n"
1189 " // assume it is in the range [0, 0.25 * dataRange].\n"
1190 " range = range != 0 ? range : 1.0;\n"
1191 " grad_mag = grad_mag / (0.25 * range);\n"
1192 " grad_mag = clamp(grad_mag, 0.0, 1.0);\n"
1193 "\n"
1194 " return vec4(g2.xyz, grad_mag);\n"
1195 "}\n");
1196 }
1197 }
1198 else
1199 {
1200 shaderStr += functionSignature +
1201 std::string("{\n"
1202 " return vec4(0.0);\n"
1203 "}\n");
1205
1206 return shaderStr;
1207}
1208
1209std::string PhaseFunctionDeclaration(
1210 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vol)
1211{
1212 std::string resStr;
1213 // to be compatible with the surface shading model,
1214 // the phase function should be normalized to 4pi instead of 1
1215 // that's why the isotropic phase function returns 1 and not 1/4pi for example
1216 if (std::abs(vol->GetProperty()->GetScatteringAnisotropy()) < 0.01)
1217 {
1218 resStr += R"***(
1219float phase_function(float cos_angle)
1220{
1221 return 1.0;
1222}
1223 )***";
1224 }
1225 else
1226 {
1227 resStr += R"***(
1228float g_anisotropy2 = in_anisotropy * in_anisotropy;
1229
1230float phase_function(float cos_angle)
1231{
1232 float d = 1.0 + g_anisotropy2 - 2.0 * in_anisotropy * cos_angle;
1233 return (1.0 - g_anisotropy2) / (d * sqrt(d));
1234}
1235
1236 )***";
1238 return resStr;
1239}
1240
1241//--------------------------------------------------------------------------
1242std::string ComputeLightingDeclaration(vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper,
1243 vtkVolume* vol, int noOfComponents, int independentComponents, int totalNumberOfLights,
1244 int numberPositionalLights, bool defaultLighting)
1245{
1246 auto glMapper = vtkOpenGLGPUVolumeRayCastMapper::SafeDownCast(mapper);
1247 vtkVolumeProperty* volProperty = vol->GetProperty();
1248 std::string shaderStr = std::string("\
1249 \nvec4 computeLighting(vec4 color, int component, float label)\
1250 \n{\
1251 \n vec4 finalColor = vec4(0.0);\n");
1252
1253 // Shading for composite blending only
1254 int const shadeReqd = volProperty->GetShade() &&
1258
1259 int const transferMode = volProperty->GetTransferFunctionMode();
1260
1261 bool const volumetricShadow = glMapper->GetVolumetricScatteringBlending() > 0.0;
1262 std::string volumetricCall = volumetricShadow
1263 ? "\n vol_shadow = volumeShadow(g_dataPos, tex_light.xyz, 0.0, component, in_volume[0], "
1264 "0, label);"
1265 : "";
1266 std::string volumetricDeclarations =
1267 volumetricShadow ? "\n float vol_shadow = 1.0;\n vec4 tex_light = vec4(0.0);\n" : "\n";
1268
1269 // If shading is required, we compute a shading gradient (used for the shading model)
1270 if (shadeReqd)
1271 {
1272 if (glMapper->GetComputeNormalFromOpacity())
1273 {
1274 // we compute the gradienty according to the volume's opacity !
1275 shaderStr +=
1276 std::string(" vec4 shading_gradient = computeDensityGradient(g_dataPos, component, "
1277 "in_volume[0], 0, label);\n");
1278 }
1279 else
1280 {
1281 // otherwise we take the scalar gradient directly
1282 shaderStr += std::string(
1283 " vec4 shading_gradient = computeGradient(g_dataPos, component, in_volume[0], 0);\n");
1284 }
1285 }
1286
1287 // If we need the scalar gradient (typically to sample a transfer function)
1288 if (volProperty->HasGradientOpacity() || volProperty->HasLabelGradientOpacity())
1289 {
1290 // If we didn't compute it before, we compute it
1291 if (!shadeReqd || glMapper->GetComputeNormalFromOpacity())
1292 {
1293 shaderStr +=
1294 std::string(" vec4 gradient = computeGradient(g_dataPos, component, in_volume[0], 0);\n");
1295 }
1296 // otherwise, we use what we already computed
1297 else
1298 {
1299 shaderStr += std::string(" vec4 gradient = shading_gradient;\n");
1300 }
1301 }
1302
1303 if (shadeReqd)
1304 {
1305 if (defaultLighting)
1306 {
1307 shaderStr += R"***(
1308 vec3 diffuse = vec3(0.0);
1309 vec3 specular = vec3(0.0);
1310 vec3 normal = shading_gradient.xyz;
1311 float normalLength = length(normal);
1312 if (normalLength > 0.0)
1313 {
1314 normal = normalize(normal);
1315 }
1316 else
1317 {
1318 normal = vec3(0.0, 0.0, 0.0);
1319 }
1320 // XXX: normal is oriented inside the volume, so we take -g_ldir/-g_vdir
1321 float nDotL = dot(normal, -g_ldir[0]);
1322 vec3 r = normalize(2.0 * nDotL * normal + g_ldir[0]);
1323 float vDotR = dot(r, -g_vdir[0]);
1324 if (nDotL < 0.0 && in_twoSidedLighting)
1325 {
1326 nDotL = -nDotL;
1327 }
1328 if (nDotL > 0.0)
1329 {
1330 diffuse = nDotL * in_diffuse[component] *
1331 in_lightDiffuseColor[0] * color.rgb;
1332 vDotR = max(vDotR, 0.0);
1333 specular = pow(vDotR, in_shininess[component]) *
1334 in_specular[component] *
1335 in_lightSpecularColor[0];
1336 }
1337 // For the headlight, ignore the light's ambient color
1338 // for now as it is causing the old mapper tests to fail
1339 finalColor.xyz = in_ambient[component] * color.rgb +
1340 diffuse + specular;
1341
1342 )***";
1343 }
1344 else if (totalNumberOfLights > 0)
1345 {
1346 shaderStr += R"***(
1347 g_fragWorldPos = g_texToView * vec4(g_dataPos, 1.0);
1348 if (g_fragWorldPos.w != 0.0)
1349 {
1350 g_fragWorldPos /= g_fragWorldPos.w;
1351 }
1352 vec3 viewDirection = normalize(-g_fragWorldPos.xyz);
1353 vec3 ambient = vec3(0,0,0);
1354 vec3 diffuse = vec3(0,0,0);
1355 vec3 specular = vec3(0,0,0);
1356 vec3 vertLightDirection;
1357 vec3 normal = normalize((in_textureToEye[0] * vec4(shading_gradient.xyz, 0.0)).xyz);
1358 vec3 lightDir;
1359 )***";
1360
1361 if (numberPositionalLights > 0)
1362 {
1363 shaderStr += R"***(
1364 for (int posNum = 0; posNum < NUMBER_POS_LIGHTS; posNum++)
1365 {
1366 float attenuation = 1.0;
1367 lightDir = in_lightDirection[posNum];
1368 vertLightDirection = (g_fragWorldPos.xyz - in_lightPosition[posNum]);
1369 float distance = length(vertLightDirection);
1370 vertLightDirection = normalize(vertLightDirection);
1371 attenuation = 1.0 /
1372 (in_lightAttenuation[posNum].x
1373 + in_lightAttenuation[posNum].y * distance
1374 + in_lightAttenuation[posNum].z * distance * distance);
1375 // per OpenGL standard cone angle is 90 or less for a spot light
1376 if (in_lightConeAngle[posNum] <= 90.0)
1377 {
1378 float coneDot = dot(vertLightDirection, lightDir);
1379 // if inside the cone
1380 if (coneDot >= cos(radians(in_lightConeAngle[posNum])))
1381 {
1382 attenuation = attenuation * pow(coneDot, in_lightExponent[posNum]);
1383 }
1384 else
1385 {
1386 attenuation = 0.0;
1387 }
1388 }
1389
1390 float nDotL = dot(normal, vertLightDirection);
1391 if (nDotL < 0.0 && in_twoSidedLighting)
1392 {
1393 nDotL = -nDotL;
1394 }
1395 if (nDotL > 0.0)
1396 {
1397 float df = max(0.0, attenuation * nDotL);
1398 diffuse += (df * in_lightDiffuseColor[posNum]);
1399 vec3 r = normalize(2.0 * nDotL * normal - vertLightDirection);
1400 float rDotV = dot(-viewDirection, r);
1401 if (rDotV < 0.0 && in_twoSidedLighting)
1402 {
1403 rDotV = -rDotV;
1404 }
1405 if (rDotV > 0.0)
1406 {
1407 float sf = attenuation * pow(rDotV, in_shininess[component]);
1408 specular += (sf * in_lightSpecularColor[posNum]);
1409 }
1410 }
1411 ambient += in_lightAmbientColor[posNum];
1412 }
1413 )***";
1414 }
1415
1416 shaderStr += R"***(
1417 for (int dirNum = NUMBER_POS_LIGHTS; dirNum < TOTAL_NUMBER_LIGHTS; dirNum++)
1418 {
1419 vertLightDirection = in_lightDirection[dirNum];
1420 float nDotL = dot(normal, vertLightDirection);
1421 if (nDotL < 0.0 && in_twoSidedLighting)
1422 {
1423 nDotL = -nDotL;
1424 }
1425 if (nDotL > 0.0)
1426 {
1427 float df = max(0.0, nDotL);
1428 diffuse += (df * in_lightDiffuseColor[dirNum]);
1429 vec3 r = normalize(2.0 * nDotL * normal - vertLightDirection);
1430 float rDotV = dot(-viewDirection, r);
1431 if (rDotV > 0.0)
1432 {
1433 float sf = pow(rDotV, in_shininess[component]);
1434 specular += (sf * in_lightSpecularColor[dirNum]);
1435 }
1436 }
1437 ambient += in_lightAmbientColor[dirNum];
1438 }
1439 finalColor.xyz = in_ambient[component] * ambient +
1440 in_diffuse[component] * diffuse * color.rgb +
1441 in_specular[component] * specular;
1442
1443 )***";
1444 }
1445 }
1446 else
1447 {
1448 shaderStr += std::string("\n finalColor = vec4(color.rgb, 0.0);");
1449 }
1450
1451 if (glMapper->GetVolumetricScatteringBlending() > 0.0 && totalNumberOfLights > 0)
1452 {
1453
1454 float vsBlend = glMapper->GetVolumetricScatteringBlending();
1455 std::string blendingFormula = std::string(" float vol_coef = ") +
1456 (vsBlend < 1.0 ? "2.0 * in_volumetricScatteringBlending * exp( - 2.0 * "
1457 "in_volumetricScatteringBlending * shading_gradient.w * color.a)"
1458 : "2.0 * (1.0 - in_volumetricScatteringBlending) * exp( - 2.0 * "
1459 "in_volumetricScatteringBlending * shading_gradient.w * color.a) + 2.0 * "
1460 "in_volumetricScatteringBlending - 1.0") +
1461 ";\n";
1462
1463 shaderStr +=
1464 (defaultLighting
1465 ? std::string()
1466 : std::string(
1467 "vec3 view_tdir = normalize((g_eyeToTexture * vec4(viewDirection, 0.0)).xyz);\n")) +
1468 R"***(
1469 vec3 secondary_contrib = vec3(0.0);
1470 vec3 tex_light = vec3(0.0);
1471 shading_gradient.w = length(shading_gradient.xyz);
1472 vec3 diffuse_light = vec3(0.0);
1473 float attenuation = 0.0;
1474 float vol_shadow = 0.0;
1475 float phase = 1.0;
1476 )***";
1477
1478 if (defaultLighting)
1479 {
1480 shaderStr += R"***(
1481 tex_light = (in_inverseTextureDatasetMatrix[0] * in_inverseVolumeMatrix[0] * vec4(in_cameraPos, 1.0)).xyz;
1482 phase = phase_function(-1); // always angle of pi
1483 vol_shadow = volumeShadow(g_dataPos, tex_light, 1.0, component, in_volume[0], 0, label);
1484 secondary_contrib += vol_shadow * phase * color.rgb * in_diffuse[component] * in_lightDiffuseColor[0];
1485 secondary_contrib += in_ambient[component] * in_lightAmbientColor[0];
1486 )***";
1487 }
1488 else
1489 {
1490 if (numberPositionalLights > 0)
1491 {
1492 shaderStr += R"***(
1493 float dist_light = 0.0;
1494 for(int posNum = 0; posNum < NUMBER_POS_LIGHTS; posNum++)
1495 {
1496 tex_light = g_lightPositionTex[posNum];
1497 vec3 light_vert = g_fragWorldPos.xyz - in_lightPosition[posNum];
1498 dist_light = length(light_vert);
1499 float light_angle = dot(normalize(light_vert), normalize(in_lightDirection[posNum]));
1500 phase = phase_function(dot(normalize(g_dataPos - tex_light), view_tdir));
1501 attenuation = 1.0 /
1502 (in_lightAttenuation[posNum].x
1503 + in_lightAttenuation[posNum].y * dist_light
1504 + in_lightAttenuation[posNum].z * dist_light * dist_light);
1505 attenuation *= max(0.0, sign(light_angle - cos(radians(in_lightConeAngle[posNum]))))
1506 * pow(light_angle, in_lightExponent[posNum]);
1507 vol_shadow = volumeShadow(g_dataPos, tex_light, 1.0, component, in_volume[0], 0, label);
1508 secondary_contrib += vol_shadow * phase * attenuation * color.rgb * in_diffuse[component] * in_lightDiffuseColor[posNum];
1509 secondary_contrib += in_ambient[component] * in_lightAmbientColor[posNum];
1510 }
1511 )***";
1512 }
1513
1514 shaderStr += R"***(
1515 for(int dirNum = NUMBER_POS_LIGHTS; dirNum < TOTAL_NUMBER_LIGHTS; dirNum++)
1516 {
1517 tex_light = g_lightDirectionTex[dirNum];
1518 phase = phase_function(dot(normalize(-tex_light), view_tdir));
1519 vol_shadow = volumeShadow(g_dataPos, tex_light, 0.0, component, in_volume[0], 0, label);
1520 secondary_contrib += vol_shadow * phase * color.rgb * in_diffuse[component] * in_lightDiffuseColor[dirNum];
1521 secondary_contrib += in_ambient[component] * in_lightAmbientColor[dirNum];
1522 }
1523 )***";
1524 }
1525
1526 shaderStr += blendingFormula +
1527 R"***(
1528 finalColor.xyz = (1.0 - vol_coef) * finalColor.xyz + vol_coef * secondary_contrib;
1529 )***";
1530 }
1531
1532 // For 1D transfers only (2D transfer functions hold scalar and
1533 // gradient-magnitude opacities combined in the same table).
1534 // For multiple inputs, a different computeGradientOpacity() signature
1535 // is defined.
1536 if (transferMode == vtkVolumeProperty::TF_1D && glMapper->GetInputCount() == 1)
1537 {
1538 if (noOfComponents == 1 || !independentComponents)
1539 {
1540 if (volProperty->HasGradientOpacity())
1541 {
1542 shaderStr += std::string("\
1543 \n if (gradient.w >= 0.0 && label == 0.0)\
1544 \n {\
1545 \n color.a *= computeGradientOpacity(gradient);\
1546 \n }");
1547 }
1548 if (volProperty->HasLabelGradientOpacity())
1549 {
1550 shaderStr += std::string("\
1551 \n if (gradient.w >= 0.0 && label > 0.0)\
1552 \n {\
1553 \n color.a *= computeGradientOpacityForLabel(gradient, label);\
1554 \n }");
1555 }
1556 }
1557 else if (noOfComponents > 1 && independentComponents && volProperty->HasGradientOpacity())
1558 {
1559 shaderStr += std::string("\
1560 \n if (gradient.w >= 0.0)\
1561 \n {\
1562 \n for (int i = 0; i < in_noOfComponents; ++i)\
1563 \n {\
1564 \n color.a = color.a *\
1565 \n computeGradientOpacity(gradient, i) * in_componentWeight[i];\
1566 \n }\
1567 \n }");
1568 }
1569 }
1570
1571 shaderStr += std::string("\
1572 \n finalColor.a = color.a;\
1573 \n return finalColor;\
1574 \n }");
1575
1576 return shaderStr;
1577}
1578
1579//--------------------------------------------------------------------------
1580std::string ComputeLightingMultiDeclaration(vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper,
1581 vtkVolume* vol, int noOfComponents, int independentComponents,
1582 int vtkNotUsed(totalNumberOfLights), bool defaultLighting)
1583{
1584 auto glMapper = vtkOpenGLGPUVolumeRayCastMapper::SafeDownCast(mapper);
1585 vtkVolumeProperty* volProperty = vol->GetProperty();
1586 std::string shaderStr = std::string();
1587
1588 // if no gradient TF is needed, don't add it into the function signature
1589 if (volProperty->HasGradientOpacity())
1590 {
1591 shaderStr += std::string("\
1592 \nvec4 computeLighting(vec3 texPos, vec4 color, const in sampler2D gradientTF, const in sampler3D volume, const in sampler2D opacityTF, const int volIdx, int component)\
1593 \n {\
1594 \n vec4 finalColor = vec4(0.0);\n");
1595 }
1596 else
1597 {
1598 shaderStr += std::string("\
1599 \nvec4 computeLighting(vec3 texPos, vec4 color, const in sampler3D volume, const in sampler2D opacityTF, const int volIdx, int component)\
1600 \n {\
1601 \n vec4 finalColor = vec4(0.0);\n");
1602 }
1603
1604 // Shading for composite blending only
1605 int const shadeReqd = volProperty->GetShade() &&
1608
1609 int const transferMode = volProperty->GetTransferFunctionMode();
1610
1611 // If shading is required, we compute a shading gradient (used for the shading model)
1612 if (shadeReqd)
1613 {
1614 /*
1615 We compute the gradient every time, because the alternative would be to test whether
1616 the volume has gradient cache or not. But as both branches will be evaluated anyway
1617 on GPU, we might as well compute the gradient every time.
1618 */
1619 if (glMapper->GetComputeNormalFromOpacity())
1620 {
1621 if (volProperty->HasGradientOpacity())
1622 {
1623 shaderStr += " vec4 shading_gradient = computeDensityGradient(texPos, component, volume, "
1624 "opacityTF, gradientTF, volIdx, 0.0);\n";
1625 }
1626 else
1627 {
1628 shaderStr += " vec4 shading_gradient = computeDensityGradient(texPos, component, volume, "
1629 "opacityTF, volIdx, 0.0);\n";
1630 }
1631 }
1632 else
1633 {
1634 shaderStr +=
1635 " vec4 shading_gradient = computeGradient(texPos, component, volume, volIdx);\n";
1636 }
1637 }
1638
1639 // If we need the scalar gradient (typically to sample a transfer function)
1640 if (volProperty->HasGradientOpacity())
1641 {
1642 if (!shadeReqd || glMapper->GetComputeNormalFromOpacity())
1643 {
1644 shaderStr += " vec4 gradient = computeGradient(texPos, component, volume, volIdx);\n";
1645 }
1646 else
1647 {
1648 // if we already computed it
1649 shaderStr += " vec4 gradient = shading_gradient;\n";
1650 }
1651 }
1652
1653 if (shadeReqd && defaultLighting)
1654 {
1655 shaderStr += std::string("\
1656 \n vec3 diffuse = vec3(0.0);\
1657 \n vec3 specular = vec3(0.0);\
1658 \n vec3 normal = shading_gradient.xyz;\
1659 \n float normalLength = length(normal);\
1660 \n if (normalLength > 0.0)\
1661 \n {\
1662 \n normal = normalize(normal);\
1663 \n }\
1664 \n else\
1665 \n {\
1666 \n normal = vec3(0.0, 0.0, 0.0);\
1667 \n }\
1668 \n // normal is oriented inside the volume (because normal = gradient, oriented inside the volume)\
1669 \n // thus we have to take minus everything\
1670 \n float nDotL = dot(normal, -g_ldir[volIdx]);\
1671 \n vec3 r = normalize(2.0 * nDotL * normal + g_ldir[volIdx]);\
1672 \n float vDotR = dot(r, -g_vdir[volIdx]);\
1673 \n if (nDotL < 0.0 && in_twoSidedLighting)\
1674 \n {\
1675 \n nDotL = -nDotL;\
1676 \n }\
1677 \n if (nDotL > 0.0)\
1678 \n {\
1679 \n diffuse = nDotL * in_diffuse[component] *\
1680 \n in_lightDiffuseColor[0] * color.rgb;\
1681 \n vDotR = max(vDotR, 0.0);\
1682 \n specular = pow(vDotR, in_shininess[component]) *\
1683 \n in_specular[component] *\
1684 \n in_lightSpecularColor[0];\
1685 \n }\
1686 \n finalColor.xyz = in_ambient[component] * color.rgb * in_lightAmbientColor[0] +\
1687 \n diffuse + specular;\
1688 \n");
1689 }
1690 else
1691 {
1692 shaderStr += std::string("\n finalColor = vec4(color.rgb, 0.0);");
1693 }
1694
1695 // For 1D transfers only (2D transfer functions hold scalar and
1696 // gradient-magnitude opacities combined in the same table).
1697 if (transferMode == vtkVolumeProperty::TF_1D)
1698 {
1699 if (volProperty->HasGradientOpacity() && (noOfComponents == 1 || !independentComponents))
1700 {
1701 shaderStr += std::string("\
1702 \n if (gradient.w >= 0.0)\
1703 \n {\
1704 \n color.a = color.a *\
1705 \n computeGradientOpacity(gradient, gradientTF);\
1706 \n }");
1707 }
1708 }
1709
1710 shaderStr += std::string("\
1711 \n finalColor.a = color.a;\
1712 \n return clamp(finalColor, 0.0, 1.0);\
1713 \n }");
1714
1715 return shaderStr;
1716}
1717
1718//--------------------------------------------------------------------------
1719std::string ComputeRayDirectionDeclaration(vtkRenderer* ren, vtkVolumeMapper* vtkNotUsed(mapper),
1720 vtkVolume* vtkNotUsed(vol), int vtkNotUsed(noOfComponents))
1721{
1723 {
1724 return std::string("\
1725 \nvec3 computeRayDirection()\
1726 \n {\
1727 \n return normalize(ip_vertexPos.xyz - g_eyePosObj.xyz);\
1728 \n }");
1729 }
1730 else
1731 {
1732 return std::string("\
1733 \nuniform vec3 in_projectionDirection;\
1734 \nvec3 computeRayDirection()\
1735 \n {\
1736 \n return normalize((in_inverseVolumeMatrix[0] *\
1737 \n vec4(in_projectionDirection, 0.0)).xyz);\
1738 \n }");
1739 }
1740}
1741
1742//--------------------------------------------------------------------------
1744 int noOfComponents, vtkVolumeProperty* volProp)
1745{
1746 std::string resStr;
1747 if (inputs.size() > 1)
1748 {
1749 // multi volume
1750 for (auto& item : inputs)
1751 {
1752 const auto& prop = item.second.Volume->GetProperty();
1753 if (prop->GetTransferFunctionMode() != vtkVolumeProperty::TF_1D)
1754 continue;
1755
1756 auto& map = item.second.RGBTablesMap;
1757 const auto numComp = map.size();
1758 resStr +=
1759 "uniform sampler2D " + ArrayBaseName(map[0]) + "[" + std::to_string(numComp) + "];\n";
1760 }
1762 else
1763 {
1764 // single volume
1766 {
1767 resStr += "uniform sampler2D " + ArrayBaseName(inputs[0].RGBTablesMap[0]) + "[" +
1768 std::to_string(noOfComponents) + "];\n";
1769 }
1770 // in case of TF_2D, the texture needed is defined with computeOpacity
1771 }
1772 return resStr;
1773}
1774
1775//--------------------------------------------------------------------------
1776std::string ComputeColorDeclaration(vtkRenderer* vtkNotUsed(ren),
1777 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), int noOfComponents,
1778 int independentComponents, std::map<int, std::string> colorTableMap)
1779{
1780 std::ostringstream ss;
1781
1782 std::string shaderStr = ss.str();
1783 if (noOfComponents == 1)
1784 {
1785 shaderStr += std::string("\
1786 \nvec4 computeColor(vec4 scalar, float opacity)\
1787 \n {\
1788 \n return clamp(computeLighting(vec4(texture2D(" +
1789 colorTableMap[0] + ",\
1790 \n vec2(scalar.w, 0.0)).xyz, opacity), 0, 0.0), 0.0, 1.0);\
1791 \n }");
1792 return shaderStr;
1793 }
1794 else if (noOfComponents > 1 && independentComponents)
1795 {
1796 std::ostringstream toString;
1797
1798 shaderStr += std::string("\
1799 \nvec4 computeColor(vec4 scalar, float opacity, int component)\
1800 \n {");
1801
1802 for (int i = 0; i < noOfComponents; ++i)
1803 {
1804 toString << i;
1805 shaderStr += std::string("\
1806 \n if (component == " +
1807 toString.str() + ")");
1808
1809 shaderStr += std::string("\
1810 \n {\
1811 \n return clamp(computeLighting(vec4(texture2D(\
1812 \n " +
1813 colorTableMap[i]);
1814 shaderStr += std::string(", vec2(\
1815 \n scalar[" +
1816 toString.str() + "],0.0)).xyz,\
1817 \n opacity)," +
1818 toString.str() + ", 0.0), 0.0, 1.0);\
1819 \n }");
1820
1821 // Reset
1822 toString.str("");
1823 toString.clear();
1824 }
1825
1826 shaderStr += std::string("\n }");
1827 return shaderStr;
1828 }
1829 else if (noOfComponents == 2 && !independentComponents)
1830 {
1831 shaderStr += std::string("\
1832 \nvec4 computeColor(vec4 scalar, float opacity)\
1833 \n {\
1834 \n return clamp(computeLighting(vec4(texture2D(" +
1835 colorTableMap[0] + ",\
1836 \n vec2(scalar.x, 0.0)).xyz,\
1837 \n opacity), 0, 0.0), 0.0, 1.0);\
1838 \n }");
1839 return shaderStr;
1840 }
1841 else
1842 {
1843 shaderStr += std::string("\
1844 \nvec4 computeColor(vec4 scalar, float opacity)\
1845 \n {\
1846 \n return clamp(computeLighting(vec4(scalar.xyz, opacity), 0, 0.0), 0.0, 1.0);\
1847 \n }");
1848 return shaderStr;
1849 }
1850}
1851
1852//--------------------------------------------------------------------------
1854 vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs, bool useGradientTF)
1855{
1856 std::ostringstream ss;
1857 int lastComponentMode = vtkVolumeInputHelper::INVALID;
1858 std::map<int, std::string> lastColorTableMap;
1859 for (auto& item : inputs)
1860 {
1861 auto prop = item.second.Volume->GetProperty();
1862 if (prop->GetTransferFunctionMode() != vtkVolumeProperty::TF_1D)
1863 continue;
1864 auto& map = item.second.RGBTablesMap;
1865 lastComponentMode = item.second.ComponentMode;
1866 lastColorTableMap = map;
1867 }
1868
1869 if (lastComponentMode == vtkVolumeInputHelper::LA)
1870 {
1871 ss << "vec4 computeColor(vec4 scalar, const in sampler2D colorTF)\
1872 \n {\
1873 \n return clamp(computeLighting(vec4(texture2D(colorTF,\
1874 \n vec2(scalar.w, 0.0)).xyz, opacity), 0), 0.0, 1.0);\
1875 \n }\n";
1876 }
1877 else
1878 {
1879 if (useGradientTF)
1880 {
1881 ss
1882 << "vec4 computeColor(vec3 texPos, vec4 scalar, float opacity, const in sampler2D colorTF, "
1883 "const in sampler2D gradientTF, const in sampler3D volume, const in sampler2D "
1884 "opacityTF, const int volIdx)\n\n"
1885 "{\n"
1886 " return clamp(computeLighting(texPos, vec4(texture2D(colorTF,\n"
1887 " vec2(scalar.w, 0.0)).xyz, opacity), gradientTF, volume, "
1888 "opacityTF,"
1889 "volIdx, 0), 0.0, 1.0);\n"
1890 "}\n";
1891 }
1892 else
1893 {
1895 << "vec4 computeColor(vec3 texPos, vec4 scalar, float opacity, const in sampler2D colorTF, "
1896 "const in sampler3D volume, const in sampler2D opacityTF, const int volIdx)\n\n"
1897 "{\n"
1898 " return clamp(computeLighting(texPos, vec4(texture2D(colorTF,\n"
1899 " vec2(scalar.w, 0.0)).xyz, opacity), volume, opacityTF,"
1900 "volIdx, 0), 0.0, 1.0);\n"
1901 "}\n";
1902 }
1903 }
1904
1905 return ss.str();
1906}
1907
1908//--------------------------------------------------------------------------
1910{
1911 std::ostringstream ss;
1912 int i = 0;
1913 for (auto& item : inputs)
1914 {
1915 auto prop = item.second.Volume->GetProperty();
1916 if (prop->GetTransferFunctionMode() != vtkVolumeProperty::TF_1D)
1917 continue;
1919 auto& map = item.second.OpacityTablesMap;
1920 const auto numComp = map.size();
1921 ss << "uniform sampler2D " << ArrayBaseName(map[0]) << "[" << numComp << "];\n";
1922 i++;
1923 }
1924
1925 ss << "float computeOpacity(vec4 scalar, const in sampler2D opacityTF)\n"
1926 "{\n"
1927 " return texture2D(opacityTF, vec2(scalar.w, 0)).r;\n"
1928 "}\n";
1929 return ss.str();
1930}
1931
1932//--------------------------------------------------------------------------
1935{
1936 std::ostringstream ss;
1937
1938 int i = 0;
1939 for (auto& item : inputs)
1940 {
1941 auto prop = item.second.Volume->GetProperty();
1942 if (prop->GetTransferFunctionMode() != vtkVolumeProperty::TF_1D || !prop->HasGradientOpacity())
1943 continue;
1945 auto& map = item.second.GradientOpacityTablesMap;
1946 const auto numComp = map.size();
1947 ss << "uniform sampler2D " << ArrayBaseName(map[0]) << "[" << numComp << "];\n";
1948 i++;
1949 }
1950
1951 ss << "float computeGradientOpacity(vec4 grad, const in sampler2D gradientTF)\n"
1952 "{\n"
1953 " return texture2D(gradientTF, vec2(grad.w, 0.0)).r;\n"
1954 "}\n";
1955 return ss.str();
1956}
1957
1958//--------------------------------------------------------------------------
1959std::string ComputeOpacityDeclaration(vtkRenderer* vtkNotUsed(ren),
1960 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), int noOfComponents,
1961 int independentComponents, std::map<int, std::string> opacityTableMap)
1962{
1963 std::ostringstream ss;
1964 ss << "uniform sampler2D " << ArrayBaseName(opacityTableMap[0]) << "[" << noOfComponents
1965 << "];\n";
1966
1967 std::string shaderStr = ss.str();
1968 if (noOfComponents > 1 && independentComponents)
1969 {
1970 shaderStr += std::string("\
1971 \nfloat computeOpacity(vec4 scalar, int component)\
1972 \n{");
1973
1974 for (int i = 0; i < noOfComponents; ++i)
1975 {
1976 std::ostringstream toString;
1977 toString << i;
1978 shaderStr += std::string("\
1979 \n if (component == " +
1980 toString.str() + ")");
1981
1982 shaderStr += std::string("\
1983 \n {\
1984 \n return texture2D(" +
1985 opacityTableMap[i]);
1986
1987 shaderStr += std::string(",vec2(scalar[" + toString.str() + "], 0)).r;\
1988 \n }");
1989 }
1990
1991 shaderStr += std::string("\n}");
1992 return shaderStr;
1993 }
1994 else if (noOfComponents == 2 && !independentComponents)
1995 {
1996 shaderStr += std::string("\
1997 \nfloat computeOpacity(vec4 scalar)\
1998 \n{\
1999 \n return texture2D(" +
2000 opacityTableMap[0] + ", vec2(scalar.y, 0)).r;\
2001 \n}");
2002 return shaderStr;
2003 }
2004 else
2005 {
2006 shaderStr += std::string("\
2007 \nfloat computeOpacity(vec4 scalar)\
2008 \n{\
2009 \n return texture2D(" +
2010 opacityTableMap[0] + ", vec2(scalar.w, 0)).r;\
2011 \n}");
2012 return shaderStr;
2013 }
2014}
2015
2016//--------------------------------------------------------------------------
2017std::string ComputeColor2DYAxisDeclaration(int noOfComponents,
2018 int vtkNotUsed(independentComponents), std::map<int, std::string> colorTableMap)
2019{
2020 if (noOfComponents == 1)
2021 {
2022 // Single component
2023 return std::string(
2024 "vec4 computeColor(vec4 scalar, float opacity)\n"
2025 "{\n"
2026 " vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
2027 " yscalar.r = yscalar.r * in_transfer2DYAxis_scale.r + in_transfer2DYAxis_bias.r;\n"
2028 " yscalar = vec4(yscalar.r);\n"
2029 " vec4 color = texture2D(" +
2030 colorTableMap[0] +
2031 ",\n"
2032 " vec2(scalar.w, yscalar.w));\n"
2033 " return computeLighting(color, 0, 0);\n"
2034 "}\n");
2035 }
2036 return std::string("vec4 computeColor(vec4 scalar, float opacity)\n"
2037 "{\n"
2038 " return vec4(0, 0, 0, 0)\n"
2039 "}\n");
2040}
2041
2042//--------------------------------------------------------------------------
2043std::string ComputeColor2DDeclaration(vtkRenderer* vtkNotUsed(ren),
2044 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), int noOfComponents,
2045 int independentComponents, std::map<int, std::string> colorTableMap, int useGradient)
2046{
2047 if (!useGradient)
2048 {
2049 return ComputeColor2DYAxisDeclaration(noOfComponents, independentComponents, colorTableMap);
2050 }
2051 if (noOfComponents == 1)
2052 {
2053 // Single component
2054 return std::string("vec4 computeColor(vec4 scalar, float opacity)\n"
2055 "{\n"
2056 " vec4 color = texture2D(" +
2057 colorTableMap[0] +
2058 ",\n"
2059 " vec2(scalar.w, g_gradients_0[0].w));\n"
2060 " return computeLighting(color, 0, 0);\n"
2061 "}\n");
2062 }
2063 else if (noOfComponents > 1 && independentComponents)
2064 {
2065 // Multiple independent components
2066 std::string shaderStr;
2067 shaderStr += std::string("vec4 computeColor(vec4 scalar, float opacity, int component)\n"
2068 "{\n");
2069
2070 for (int i = 0; i < noOfComponents; ++i)
2071 {
2072 std::ostringstream toString;
2073 toString << i;
2074 std::string const num = toString.str();
2075 shaderStr += std::string(" if (component == " + num +
2076 ")\n"
2077 " {\n"
2078 " vec4 color = texture2D(" +
2079 colorTableMap[i] +
2080 ",\n"
2081 " vec2(scalar[" +
2082 num + "], g_gradients_0[" + num +
2083 "].w));\n"
2084 " return computeLighting(color, " +
2085 num +
2086 ", 0.0);\n"
2087 " }\n");
2088 }
2089 shaderStr += std::string("}\n");
2090
2091 return shaderStr;
2092 }
2093 else if (noOfComponents == 2 && !independentComponents)
2094 {
2095 // Dependent components (Luminance/ Opacity)
2096 return std::string("vec4 computeColor(vec4 scalar, float opacity)\n"
2097 "{\n"
2098 " vec4 color = texture2D(" +
2099 colorTableMap[0] +
2100 ",\n"
2101 " vec2(scalar.x, g_gradients_0[0].w));\n"
2102 " return computeLighting(color, 0, 0.0);\n"
2103 "}\n");
2104 }
2105 else
2106 {
2107 return std::string("vec4 computeColor(vec4 scalar, float opacity)\n"
2108 "{\n"
2109 " return computeLighting(vec4(scalar.xyz, opacity), 0, 0.0);\n"
2110 "}\n");
2111 }
2112}
2113
2114//--------------------------------------------------------------------------
2116{
2117 std::ostringstream ss;
2118 int i = 0;
2119 for (auto& item : inputs)
2120 {
2121 auto prop = item.second.Volume->GetProperty();
2122 if (prop->GetTransferFunctionMode() != vtkVolumeProperty::TF_2D)
2123 continue;
2124
2125 auto& map = item.second.TransferFunctions2DMap;
2126 const auto numComp = map.size();
2127 ss << "uniform sampler2D " << ArrayBaseName(map[0]) << "[" << numComp << "];\n";
2128 i++;
2129 }
2130
2131 std::string result = ss.str() +
2132 std::string("uniform sampler3D in_transfer2DYAxis;\n"
2133 "uniform vec4 in_transfer2DYAxis_scale;\n"
2134 "uniform vec4 in_transfer2DYAxis_bias;\n");
2135
2136 return result;
2137}
2138
2139//--------------------------------------------------------------------------
2140std::string ComputeOpacity2DDeclaration(vtkRenderer* vtkNotUsed(ren),
2141 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), int noOfComponents,
2142 int independentComponents, std::map<int, std::string> opacityTableMap, int useGradient)
2143{
2144 std::ostringstream toString;
2145 if (noOfComponents > 1 && independentComponents)
2146 {
2147 // Multiple independent components
2148 toString << "float computeOpacity(vec4 scalar, int component)\n"
2149 "{\n";
2150 if (!useGradient)
2151 {
2152 toString
2153 << "vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
2154 "for (int i = 0; i < 4; ++i)\n"
2155 "{\n"
2156 " yscalar[i] = yscalar[i] * in_transfer2DYAxis_scale[i] + in_transfer2DYAxis_bias[i];\n"
2157 "}\n";
2158 if (noOfComponents == 1)
2159 {
2160 toString << "yscalar = vec4(yscalar.r);\n";
2161 }
2162 }
2163
2164 for (int i = 0; i < noOfComponents; ++i)
2165 {
2166 if (useGradient)
2167 {
2168 toString << " if (component == " << i
2169 << ")\n"
2170 " {\n"
2171 " return texture2D("
2172 << opacityTableMap[i]
2173 << ",\n"
2174 " vec2(scalar["
2175 << i << "], g_gradients_0[" << i
2176 << "].w)).a;\n"
2177 " }\n";
2178 }
2179 else
2180 {
2181 toString << " if (component == " << i
2182 << ")\n"
2183 " {\n"
2184 " return texture2D("
2185 << opacityTableMap[i]
2186 << ",\n"
2187 " vec2(scalar["
2188 << i << "], yscalar[" << i
2189 << "])).a;\n"
2190 " }\n";
2191 }
2192 }
2193
2194 toString << "}\n";
2195 }
2196
2197 else if (noOfComponents == 2 && !independentComponents)
2198 {
2199 if (useGradient)
2200 {
2201 // Dependent components (Luminance/ Opacity)
2202 toString << "float computeOpacity(vec4 scalar)\n"
2203 "{\n"
2204 " return texture2D(" +
2205 opacityTableMap[0] +
2206 ",\n"
2207 " vec2(scalar.y, g_gradients_0[0].w)).a;\n"
2208 "}\n";
2209 }
2210 else
2211 {
2212 // Dependent components (Luminance/ Opacity)
2213 toString << "float computeOpacity(vec4 scalar)\n"
2214 "{\n"
2215 " return texture2D(" +
2216 opacityTableMap[0] +
2217 ",\n"
2218 " vec2(scalar.y, yscalar.y)).a;\n"
2219 "}\n";
2220 }
2221 }
2222
2223 else
2224 {
2225 if (useGradient)
2226 {
2227 // Dependent compoennts (RGBA) || Single component
2228 toString << "float computeOpacity(vec4 scalar)\n"
2229 "{\n"
2230 " return texture2D(" +
2231 opacityTableMap[0] +
2232 ",\n"
2233 " vec2(scalar.a, g_gradients_0[0].w)).a;\n"
2234 "}\n";
2235 }
2236 else
2237 {
2238 // Dependent compoennts (RGBA) || Single component
2239 toString
2240 << "float computeOpacity(vec4 scalar)\n"
2241 "{\n"
2242 " vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
2243 " yscalar.r = yscalar.r * in_transfer2DYAxis_scale.r + in_transfer2DYAxis_bias.r;\n"
2244 " yscalar = vec4(yscalar.r);\n"
2245 " return texture2D(" +
2246 opacityTableMap[0] +
2247 ",\n"
2248 " vec2(scalar.a, yscalar.w)).a;\n"
2249 "}\n";
2250 }
2251 }
2252 return toString.str();
2253}
2254
2255//--------------------------------------------------------------------------
2256std::string ComputeVolumetricShadowDec(vtkOpenGLGPUVolumeRayCastMapper* mapper,
2257 vtkVolume* vtkNotUsed(vol), int noOfComponents, int independentComponents,
2258 vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs, int useGradYAxis)
2259{
2260 std::string resStr;
2261 std::string declarations;
2262 std::string functionSignature;
2263 std::string opacityEval;
2264 std::string rayInit;
2265
2266 const size_t numInputs = inputs.size();
2267 const bool hasGradOp = ::HasGradientOpacity(inputs);
2268
2269 // for now, shadow is mono-chromatic (we only sample opacity)
2270 // it could be RGB
2271
2272 functionSignature = "float volumeShadow(vec3 sample_position, vec3 light_pos_dir, float is_Pos, "
2273 " in int c, in sampler3D volume, " +
2274 (numInputs > 1 ? std::string("in sampler2D opacityTF, ") : std::string()) +
2275 (numInputs > 1 && hasGradOp ? std::string("in sampler2D gradTF, ") : std::string()) +
2276 "int index, float label)\n";
2277
2278 declarations +=
2279 R"***(
2280 float shadow = 1.0;
2281 vec3 direction = vec3(0.0);
2282 vec3 norm_dir = vec3(0.0);
2283 float maxdist = 0.0;
2284 float scalar;
2285 vec4 gradient;
2286 float opacity = 0.0;
2287 vec3 color;
2288 Ray ray;
2289 Hit hit;
2290 float sampled_dist = 0.0;
2291 vec3 sampled_point = vec3(0.0);
2292 )***";
2293
2294 rayInit +=
2295 R"***(
2296 // direction is light_pos_dir when light is directional
2297 // and light_pos_dir - sample_position when positional
2298 direction = light_pos_dir - is_Pos * sample_position;
2299 norm_dir = normalize(direction);
2300 // introduce little offset to avoid sampling shadows at the exact
2301 // sample position
2302 sample_position += g_lengthStep * norm_dir;
2303 direction = light_pos_dir - is_Pos * sample_position;
2304 ray.origin = sample_position;
2305 ray.dir = norm_dir;
2306 safe_0_vector(ray);
2307 ray.invDir = 1.0/ray.dir;
2308 if(!BBoxIntersect(vec3(0.0), vec3(1.0), ray, hit))
2309 {
2310 // it can happen around the bounding box
2311 return 1.0;
2312 }
2313 if(hit.tmax < g_lengthStep)
2314 {
2315 // if we're too close to the bounding box
2316 return 1.0;
2317 }
2318 // in case of directional light, we want direction not to be normalized but to go
2319 // all the way to the bbox
2320 direction *= pow(hit.tmax / length(direction), 1.0 - is_Pos);
2321 maxdist = min(hit.tmax, length(direction));
2322 maxdist = min(in_giReach, maxdist);
2323 if(maxdist < EPSILON) return 1.0;
2324
2325 )***";
2326
2327 // slight imprecision for the last sample : it can be something else (less) than g_lengthStep
2328 // because the last step is clamped to the end of the ray
2329 opacityEval += " scalar = texture3D(volume, sampled_point)[c];\n"
2330 " scalar = scalar * in_volume_scale[index][c] + in_volume_bias[index][c];\n";
2332 mapper, inputs, noOfComponents, independentComponents, useGradYAxis, "sampled_point", true);
2333
2334 resStr += functionSignature + "{\n" + declarations + rayInit +
2335 R"***(
2336 float current_dist = 0.0;
2337 float current_step = g_lengthStep;
2338 float clamped_step = 0.0;
2339 while(current_dist < maxdist)
2340 {
2341 clamped_step = min(maxdist - current_dist, current_step);
2342 sampled_dist = current_dist + clamped_step * g_jitterValue;
2343 sampled_point = sample_position + sampled_dist * norm_dir;
2344 )***" +
2345 opacityEval +
2346 R"***(
2347 shadow *= 1.0 - opacity;
2348 current_dist += current_step;
2349 }
2350 return shadow;
2351}
2352 )***";
2353
2354 return resStr;
2355}
2356
2357//--------------------------------------------------------------------------
2358std::string ShadingDeclarationVertex(
2359 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
2360{
2361 return std::string();
2362}
2363
2364//--------------------------------------------------------------------------
2365std::string ShadingDeclarationFragment(
2366 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
2367{
2369 {
2370 return std::string("\
2371 \n bool l_firstValue;\
2372 \n vec4 l_maxValue;");
2373 }
2375 {
2376 return std::string("\
2377 \n bool l_firstValue;\
2378 \n vec4 l_minValue;");
2379 }
2381 {
2382 return std::string("\
2383 \n uvec4 l_numSamples;\
2384 \n vec4 l_avgValue;");
2385 }
2386 else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
2387 {
2388 return std::string("\
2389 \n vec4 l_sumValue;");
2390 }
2391 else if (mapper->GetBlendMode() == vtkVolumeMapper::ISOSURFACE_BLEND)
2392 {
2393 return std::string("\
2394 \n int l_initialIndex = 0;\
2395 \n float l_normValues[NUMBER_OF_CONTOURS + 2];");
2396 }
2397 else
2398 {
2399 return std::string();
2400 }
2401}
2402
2403//--------------------------------------------------------------------------
2404std::string ShadingInit(
2405 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
2406{
2409 return std::string("\
2410 \n // We get data between 0.0 - 1.0 range\
2411 \n l_firstValue = true;\
2412 \n l_maxValue = vec4(0.0);");
2413 }
2415 {
2416 return std::string("\
2417 \n //We get data between 0.0 - 1.0 range\
2418 \n l_firstValue = true;\
2419 \n l_minValue = vec4(1.0);");
2420 }
2422 {
2423 return std::string("\
2424 \n //We get data between 0.0 - 1.0 range\
2425 \n l_avgValue = vec4(0.0);\
2426 \n // Keep track of number of samples\
2427 \n l_numSamples = uvec4(0);");
2428 }
2429 else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
2430 {
2431 return std::string("\
2432 \n //We get data between 0.0 - 1.0 range\
2433 \n l_sumValue = vec4(0.0);");
2434 }
2435 else if (mapper->GetBlendMode() == vtkVolumeMapper::ISOSURFACE_BLEND)
2437 return std::string("\
2438 \n#if NUMBER_OF_CONTOURS\
2439 \n l_normValues[0] = -1e20; //-infinity\
2440 \n l_normValues[NUMBER_OF_CONTOURS+1] = +1e20; //+infinity\
2441 \n for (int i = 0; i < NUMBER_OF_CONTOURS; i++)\
2442 \n {\
2443 \n l_normValues[i+1] = (in_isosurfacesValues[i] - in_scalarsRange[0].x) / \
2444 \n (in_scalarsRange[0].y - in_scalarsRange[0].x);\
2445 \n }\
2446 \n#endif\
2447 ");
2448 }
2449 else
2450 {
2451 return std::string();
2452 }
2453}
2454
2455//--------------------------------------------------------------------------
2456std::string GradientCacheDec(vtkRenderer* vtkNotUsed(ren), vtkVolume* vtkNotUsed(vol),
2457 vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs, int independentComponents = 0)
2458{
2459 const int numInputs = static_cast<int>(inputs.size());
2460 const int comp = numInputs == 1 ?
2461 // Dependent components use a single opacity lut.
2462 (!independentComponents ? 1 : numInputs)
2463 :
2464 // Independent components not supported with multiple-inputs
2465 1;
2466
2467 std::ostringstream toShader;
2468 for (const auto& item : inputs)
2469 {
2470 auto& input = item.second;
2471 if (input.Volume->GetProperty()->HasGradientOpacity())
2472 {
2473 toShader << "vec4 " << input.GradientCacheName << "[" << comp << "];\n";
2474 }
2475 }
2476
2477 return toShader.str();
2478}
2479
2480//--------------------------------------------------------------------------
2481std::string PreComputeGradientsImpl(vtkRenderer* vtkNotUsed(ren), vtkVolume* vtkNotUsed(vol),
2482 int noOfComponents = 1, int independentComponents = 0)
2483{
2484 std::ostringstream shader;
2485 if (independentComponents)
2486 {
2487 if (noOfComponents == 1)
2488 {
2489 shader << "g_gradients_0[0] = computeGradient(g_dataPos, 0, in_volume[0], 0);\n";
2490 }
2491 else
2492 {
2493 // Multiple components
2494 shader << "for (int comp = 0; comp < in_noOfComponents; comp++)\n"
2495 "{\n"
2496 " g_gradients_0[comp] = computeGradient(g_dataPos, comp, in_volume[0], 0);\n"
2497 "}\n";
2498 }
2499 }
2500 else
2501 {
2502 shader << "g_gradients_0[0] = computeGradient(g_dataPos, 0, in_volume[0], 0);\n";
2503 }
2504
2505 return shader.str();
2506}
2507
2508//--------------------------------------------------------------------------
2509std::string ShadingMultipleInputs(
2510 vtkVolumeMapper* mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs)
2511{
2512 std::ostringstream toShaderStr;
2513 toShaderStr << " if (!g_skip)\n"
2514 " {\n"
2515 " vec3 texPos;\n";
2516
2517 switch (mapper->GetBlendMode())
2518 {
2520 default:
2521 {
2522 int i = 0;
2523 for (auto& item : inputs)
2524 {
2525 auto& input = item.second;
2526 auto property = input.Volume->GetProperty();
2527 // Transformation index. Index 0 refers to the global bounding-box.
2528 const auto idx = i + 1;
2529 toShaderStr <<
2530 // From global texture coordinates (bbox) to volume_i texture coords.
2531 // texPos = T * g_dataPos
2532 // T = T_dataToTex1 * T_worldToData * T_bboxTexToWorld;
2533 " texPos = (in_cellToPoint[" << idx << "] * in_inverseTextureDatasetMatrix[" << idx
2534 << "] * in_inverseVolumeMatrix[" << idx
2535 << "] *\n"
2536 " in_volumeMatrix[0] * in_textureDatasetMatrix[0] * "
2537 "vec4(g_dataPos.xyz, 1.0)).xyz;\n"
2538 " if ((all(lessThanEqual(texPos, vec3(1.0))) &&\n"
2539 " all(greaterThanEqual(texPos, vec3(0.0)))))\n"
2540 " {\n"
2541 " vec4 scalar = texture3D(in_volume["
2542 << i
2543 << "], texPos);\n"
2544 " scalar = scalar * in_volume_scale["
2545 << i << "] + in_volume_bias[" << i
2546 << "];\n"
2547 " scalar = vec4(scalar.r);\n"
2548 " g_srcColor = vec4(0.0);\n";
2549
2550 if (property->GetTransferFunctionMode() == vtkVolumeProperty::TF_1D)
2551 {
2552 std::string gradientopacity_param = (property->HasGradientOpacity())
2553 ? input.GradientOpacityTablesMap[0] + std::string(", ")
2554 : std::string();
2555
2556 toShaderStr << " g_srcColor.a = computeOpacity(scalar,"
2557 << input.OpacityTablesMap[0]
2558 << ");\n"
2559 " if (g_srcColor.a > 0.0)\n"
2560 " {\n"
2561 " g_srcColor = computeColor(texPos, scalar, g_srcColor.a, "
2562 << input.RGBTablesMap[0] << ", " << gradientopacity_param << "in_volume[" << i
2563 << "], " << input.OpacityTablesMap[0] << ", " << i << ");\n";
2564
2565 if (property->HasGradientOpacity())
2566 {
2567 const auto& grad = input.GradientCacheName;
2568 toShaderStr << " " << grad << "[0] = computeGradient(texPos, 0, "
2569 << "in_volume[" << i << "], " << i
2570 << ");\n"
2571 " if ("
2572 << grad
2573 << "[0].w >= 0.0)\n"
2574 " {\n"
2575 " g_srcColor.a *= computeGradientOpacity("
2576 << grad << "[0], " << input.GradientOpacityTablesMap[0]
2577 << ");\n"
2578 " }\n";
2579 }
2580 }
2581 else if (property->GetTransferFunctionMode() == vtkVolumeProperty::TF_2D)
2582 {
2583 const auto& grad = input.GradientCacheName;
2584 toShaderStr <<
2585 // Sample 2DTF directly
2586 " " << grad << "[0] = computeGradient(texPos, 0, "
2587 << "in_volume[" << i << "], " << i
2588 << ");\n"
2589 " g_srcColor = texture2D("
2590 << input.TransferFunctions2DMap[0] << ", vec2(scalar.r, "
2591 << input.GradientCacheName
2592 << "[0].w));\n"
2593 " if (g_srcColor.a > 0.0)\n"
2594 " {\n";
2595 }
2596
2597 toShaderStr
2598 << " g_srcColor.rgb *= g_srcColor.a;\n"
2599 " g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;\n"
2600 " }\n"
2601 " }\n\n";
2602
2603 i++;
2604 }
2605 }
2606 break;
2607 }
2608 toShaderStr << " }\n";
2609
2610 return toShaderStr.str();
2611}
2612
2613//--------------------------------------------------------------------------
2614std::string ShadingSingleInput(vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper,
2615 vtkVolume* vtkNotUsed(vol), vtkImageData* maskInput, vtkVolumeTexture* mask, int maskType,
2616 int noOfComponents, int independentComponents = 0)
2617{
2618 auto glMapper = vtkOpenGLGPUVolumeRayCastMapper::SafeDownCast(mapper);
2619
2620 std::string shaderStr;
2621
2622 shaderStr += std::string("\
2623 \n if (!g_skip)\
2624 \n {\
2625 \n vec4 scalar;\
2626 \n");
2628 {
2629 shaderStr += std::string("\
2630 \n // Compute IJK vertex position for current sample in the rectilinear grid\
2631 \n vec4 dataPosWorld = in_volumeMatrix[0] * in_textureDatasetMatrix[0] * vec4(g_dataPos, 1.0);\
2632 \n dataPosWorld = dataPosWorld / dataPosWorld.w;\
2633 \n dataPosWorld.w = 1.0;\
2634 \n ivec3 ijk = ivec3(0);\
2635 \n vec3 ijkTexCoord = vec3(0.0);\
2636 \n vec3 pCoords = vec3(0.0);\
2637 \n vec3 xPrev, xNext, tmp;\
2638 \n int sz = textureSize(in_coordTexs, 0);\
2639 \n vec4 dataPosWorldScaled = dataPosWorld * vec4(in_coordsScale, 1.0) +\
2640 \n vec4(in_coordsBias, 1.0);\
2641 \n for (int j = 0; j < 3; ++j)\
2642 \n {\
2643 \n xPrev = texture1D(in_coordTexs, 0.0).xyz;\
2644 \n xNext = texture1D(in_coordTexs, (in_coordTexSizes[j] - 1) / sz).xyz;\
2645 \n if (xNext[j] < xPrev[j])\
2646 \n {\
2647 \n tmp = xNext;\
2648 \n xNext = xPrev;\
2649 \n xPrev = tmp;\
2650 \n }\
2651 \n for (int i = 0; i < int(in_coordTexSizes[j]); i++)\
2652 \n {\
2653 \n xNext = texture1D(in_coordTexs, (i + 0.5) / sz).xyz;\
2654 \n if (dataPosWorldScaled[j] >= xPrev[j] && dataPosWorldScaled[j] < xNext[j])\
2655 \n {\
2656 \n ijk[j] = i - 1;\
2657 \n pCoords[j] = (dataPosWorldScaled[j] - xPrev[j]) / (xNext[j] - xPrev[j]);\
2658 \n break;\
2659 \n }\
2660 \n else if (dataPosWorldScaled[j] == xNext[j])\
2661 \n {\
2662 \n ijk[j] = i - 1;\
2663 \n pCoords[j] = 1.0;\
2664 \n break;\
2665 \n }\
2666 \n xPrev = xNext;\
2667 \n }\
2668 \n ijkTexCoord[j] = (ijk[j] + pCoords[j]) / in_coordTexSizes[j];\
2669 \n }\
2670 \n scalar = texture3D(in_volume[0], sign(in_cellSpacing[0]) * ijkTexCoord);\
2671 \n");
2672 }
2673 else
2674 {
2675 shaderStr += std::string("\
2676 \n scalar = texture3D(in_volume[0], g_dataPos);\
2677 \n");
2678 }
2679
2680 // simulate old intensity textures
2681 if (noOfComponents == 1)
2682 {
2683 shaderStr += std::string("\
2684 \n scalar.r = scalar.r * in_volume_scale[0].r + in_volume_bias[0].r;\
2685 \n scalar = vec4(scalar.r);");
2686 }
2687 else
2688 {
2689 // handle bias and scale
2690 shaderStr += std::string("\
2691 \n scalar = scalar * in_volume_scale[0] + in_volume_bias[0];");
2692 }
2693
2695 {
2696 if (noOfComponents > 1)
2697 {
2698 if (!independentComponents)
2699 {
2700 shaderStr += std::string("\
2701 \n if (l_maxValue.w < scalar.w || l_firstValue)\
2702 \n {\
2703 \n l_maxValue = scalar;\
2704 \n }\
2705 \n\
2706 \n if (l_firstValue)\
2707 \n {\
2708 \n l_firstValue = false;\
2709 \n }");
2710 }
2711 else
2712 {
2713 shaderStr += std::string("\
2714 \n for (int i = 0; i < in_noOfComponents; ++i)\
2715 \n {\
2716 \n if (l_maxValue[i] < scalar[i] || l_firstValue)\
2717 \n {\
2718 \n l_maxValue[i] = scalar[i];\
2719 \n }\
2720 \n }\
2721 \n if (l_firstValue)\
2722 \n {\
2723 \n l_firstValue = false;\
2724 \n }");
2725 }
2726 }
2727 else
2728 {
2729 shaderStr += std::string("\
2730 \n if (l_maxValue.w < scalar.x || l_firstValue)\
2731 \n {\
2732 \n l_maxValue.w = scalar.x;\
2733 \n }\
2734 \n\
2735 \n if (l_firstValue)\
2736 \n {\
2737 \n l_firstValue = false;\
2738 \n }");
2739 }
2740 }
2742 {
2743 if (noOfComponents > 1)
2744 {
2745 if (!independentComponents)
2746 {
2747 shaderStr += std::string("\
2748 \n if (l_minValue.w > scalar.w || l_firstValue)\
2749 \n {\
2750 \n l_minValue = scalar;\
2751 \n }\
2752 \n\
2753 \n if (l_firstValue)\
2754 \n {\
2755 \n l_firstValue = false;\
2756 \n }");
2757 }
2758 else
2759 {
2760 shaderStr += std::string("\
2761 \n for (int i = 0; i < in_noOfComponents; ++i)\
2762 \n {\
2763 \n if (l_minValue[i] < scalar[i] || l_firstValue)\
2764 \n {\
2765 \n l_minValue[i] = scalar[i];\
2766 \n }\
2767 \n }\
2768 \n if (l_firstValue)\
2769 \n {\
2770 \n l_firstValue = false;\
2771 \n }");
2772 }
2773 }
2774 else
2775 {
2776 shaderStr += std::string("\
2777 \n if (l_minValue.w > scalar.x || l_firstValue)\
2778 \n {\
2779 \n l_minValue.w = scalar.x;\
2780 \n }\
2781 \n\
2782 \n if (l_firstValue)\
2783 \n {\
2784 \n l_firstValue = false;\
2785 \n }");
2786 }
2787 }
2789 {
2790 if (noOfComponents > 1 && independentComponents)
2791 {
2792 shaderStr += std::string("\
2793 \n for (int i = 0; i < in_noOfComponents; ++i)\
2794 \n {\
2795 \n // Get the intensity in volume scalar range\
2796 \n float intensity = in_scalarsRange[i][0] +\
2797 \n (in_scalarsRange[i][1] -\
2798 \n in_scalarsRange[i][0]) * scalar[i];\
2799 \n if (in_averageIPRange.x <= intensity &&\
2800 \n intensity <= in_averageIPRange.y)\
2801 \n {\
2802 \n l_avgValue[i] += computeOpacity(scalar, i) * scalar[i];\
2803 \n ++l_numSamples[i];\
2804 \n }\
2805 \n }");
2806 }
2807 else
2808 {
2809 shaderStr += std::string("\
2810 \n // Get the intensity in volume scalar range\
2811 \n float intensity = in_scalarsRange[0][0] +\
2812 \n (in_scalarsRange[0][1] -\
2813 \n in_scalarsRange[0][0]) * scalar.x;\
2814 \n if (in_averageIPRange.x <= intensity &&\
2815 \n intensity <= in_averageIPRange.y)\
2816 \n {\
2817 \n l_avgValue.x += computeOpacity(scalar) * scalar.x;\
2818 \n ++l_numSamples.x;\
2819 \n }");
2820 }
2821 }
2822 else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
2823 {
2824 if (noOfComponents > 1 && independentComponents)
2825 {
2826 shaderStr += std::string("\
2827 \n for (int i = 0; i < in_noOfComponents; ++i)\
2828 \n {\
2829 \n float opacity = computeOpacity(scalar, i);\
2830 \n l_sumValue[i] = l_sumValue[i] + opacity * scalar[i];\
2831 \n }");
2832 }
2833 else
2834 {
2835 shaderStr += std::string("\
2836 \n float opacity = computeOpacity(scalar);\
2837 \n l_sumValue.x = l_sumValue.x + opacity * scalar.x;");
2838 }
2839 }
2840 else if (mapper->GetBlendMode() == vtkVolumeMapper::ISOSURFACE_BLEND)
2841 {
2842 shaderStr += std::string("\
2843 \n#if NUMBER_OF_CONTOURS\
2844 \n int maxComp = 0;");
2845
2846 std::string compParamStr = "";
2847 if (noOfComponents > 1 && independentComponents)
2848 {
2849 shaderStr += std::string("\
2850 \n for (int i = 1; i < in_noOfComponents; ++i)\
2851 \n {\
2852 \n if (in_componentWeight[i] > in_componentWeight[maxComp])\
2853 \n maxComp = i;\
2854 \n }");
2855 compParamStr = ", maxComp";
2856 }
2857 shaderStr += std::string("\
2858 \n if (g_currentT == 0)\
2859 \n {\
2860 \n l_initialIndex = findIsoSurfaceIndex(scalar[maxComp], l_normValues);\
2861 \n }\
2862 \n else\
2863 \n {\
2864 \n float s;\
2865 \n bool shade = false;\
2866 \n l_initialIndex = clamp(l_initialIndex, 0, NUMBER_OF_CONTOURS);\
2867 \n if (scalar[maxComp] < l_normValues[l_initialIndex])\
2868 \n {\
2869 \n s = l_normValues[l_initialIndex];\
2870 \n l_initialIndex--;\
2871 \n shade = true;\
2872 \n }\
2873 \n if (scalar[maxComp] > l_normValues[l_initialIndex+1])\
2874 \n {\
2875 \n s = l_normValues[l_initialIndex+1];\
2876 \n l_initialIndex++;\
2877 \n shade = true;\
2878 \n }\
2879 \n if (shade == true)\
2880 \n {\
2881 \n vec4 vs = vec4(s);\
2882 \n g_srcColor.a = computeOpacity(vs " +
2883 compParamStr + ");\
2884 \n g_srcColor = computeColor(vs, g_srcColor.a " +
2885 compParamStr + ");\
2886 \n g_srcColor.rgb *= g_srcColor.a;\
2887 \n g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;\
2888 \n }\
2889 \n }\
2890 \n#endif");
2891 }
2892 else if (mapper->GetBlendMode() == vtkVolumeMapper::SLICE_BLEND)
2893 {
2894 shaderStr += std::string("\
2895 \n // test if the intersection is inside the volume bounds\
2896 \n if (any(greaterThan(g_dataPos, vec3(1.0))) || any(lessThan(g_dataPos, vec3(0.0))))\
2897 \n {\
2898 \n discard;\
2899 \n }\
2900 \n float opacity = computeOpacity(scalar);\
2901 \n g_fragColor = computeColor(scalar, opacity);\
2902 \n g_fragColor.rgb *= opacity;\
2903 \n g_exit = true;");
2904 }
2905 else if (mapper->GetBlendMode() == vtkVolumeMapper::COMPOSITE_BLEND)
2906 {
2907 if (noOfComponents > 1 && independentComponents)
2908 {
2909 shaderStr += std::string("\
2910 \n vec4 color[4]; vec4 tmp = vec4(0.0);\
2911 \n float totalAlpha = 0.0;\
2912 \n for (int i = 0; i < in_noOfComponents; ++i)\
2913 \n {\
2914 ");
2915 if (glMapper->GetUseDepthPass() &&
2917 {
2918 shaderStr += std::string("\
2919 \n // Data fetching from the red channel of volume texture\
2920 \n float opacity = computeOpacity(scalar, i);\
2921 \n if (opacity > 0.0)\
2922 \n {\
2923 \n g_srcColor.a = opacity;\
2924 \n }\
2925 \n }");
2926 }
2927 else if (!mask || !maskInput || maskType != vtkGPUVolumeRayCastMapper::LabelMapMaskType)
2928 {
2929 shaderStr += std::string("\
2930 \n // Data fetching from the red channel of volume texture\
2931 \n color[i][3] = computeOpacity(scalar, i);\
2932 \n color[i] = computeColor(scalar, color[i][3], i);\
2933 \n totalAlpha += color[i][3] * in_componentWeight[i];\
2934 \n }\
2935 \n if (totalAlpha > 0.0)\
2936 \n {\
2937 \n for (int i = 0; i < in_noOfComponents; ++i)\
2938 \n {\
2939 \n // Only let visible components contribute to the final color\
2940 \n if (in_componentWeight[i] <= 0) continue;\
2941 \n\
2942 \n tmp.x += color[i].x * color[i].w * in_componentWeight[i];\
2943 \n tmp.y += color[i].y * color[i].w * in_componentWeight[i];\
2944 \n tmp.z += color[i].z * color[i].w * in_componentWeight[i];\
2945 \n tmp.w += ((color[i].w * color[i].w)/totalAlpha);\
2946 \n }\
2947 \n }\
2948 \n g_fragColor = (1.0f - g_fragColor.a) * tmp + g_fragColor;");
2949 }
2950 }
2951 else if (glMapper->GetUseDepthPass() &&
2953 {
2954 shaderStr += std::string("\
2955 \n g_srcColor = vec4(0.0);\
2956 \n g_srcColor.a = computeOpacity(scalar);");
2957 }
2958 else
2959 {
2960 if (!mask || !maskInput || maskType != vtkGPUVolumeRayCastMapper::LabelMapMaskType)
2961 {
2962 shaderStr += std::string("\
2963 \n g_srcColor = vec4(0.0);\
2964 \n g_srcColor.a = computeOpacity(scalar);\
2965 \n if (g_srcColor.a > 0.0)\
2966 \n {\
2967 \n g_srcColor = computeColor(scalar, g_srcColor.a);");
2968 }
2969
2970 shaderStr += std::string("\
2971 \n // Opacity calculation using compositing:\
2972 \n // Here we use front to back compositing scheme whereby\
2973 \n // the current sample value is multiplied to the\
2974 \n // currently accumulated alpha and then this product\
2975 \n // is subtracted from the sample value to get the\
2976 \n // alpha from the previous steps. Next, this alpha is\
2977 \n // multiplied with the current sample colour\
2978 \n // and accumulated to the composited colour. The alpha\
2979 \n // value from the previous steps is then accumulated\
2980 \n // to the composited colour alpha.\
2981 \n g_srcColor.rgb *= g_srcColor.a;\
2982 \n g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;");
2983
2984 if (!mask || !maskInput || maskType != vtkGPUVolumeRayCastMapper::LabelMapMaskType)
2985 {
2986 shaderStr += std::string("\
2987 \n }");
2988 }
2989 }
2990 }
2991 else
2992 {
2993 shaderStr += std::string();
2994 }
2995
2996 shaderStr += std::string("\
2997 \n }");
2998 return shaderStr;
2999}
3000
3001//--------------------------------------------------------------------------
3002std::string PickingActorPassExit(
3003 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3004{
3005 return std::string("\
3006 \n // Special coloring mode which renders the Prop Id in fragments that\
3007 \n // have accumulated certain level of opacity. Used during the selection\
3008 \n // pass vtkHardwareSelection::ACTOR_PASS.\
3009 \n if (g_fragColor.a > 3.0/ 255.0)\
3010 \n {\
3011 \n gl_FragData[0] = vec4(in_propId, 1.0);\
3012 \n }\
3013 \n else\
3014 \n {\
3015 \n gl_FragData[0] = vec4(0.0);\
3016 \n }\
3017 \n return;");
3018};
3019
3020//--------------------------------------------------------------------------
3021std::string PickingIdLow24PassExit(
3022 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3023{
3024 return std::string("\
3025 \n // Special coloring mode which renders the voxel index in fragments that\
3026 \n // have accumulated certain level of opacity. Used during the selection\
3027 \n // pass vtkHardwareSelection::ID_LOW24.\
3028 \n if (g_fragColor.a > 3.0/ 255.0)\
3029 \n {\
3030 \n uvec3 volumeDim = uvec3(in_textureExtentsMax - in_textureExtentsMin);\
3031 \n uvec3 voxelCoords = uvec3(volumeDim * g_dataPos);\
3032 \n // vtkHardwareSelector assumes index 0 to be empty space, so add uint(1).\
3033 \n uint idx = volumeDim.x * volumeDim.y * voxelCoords.z +\
3034 \n volumeDim.x * voxelCoords.y + voxelCoords.x + uint(1);\
3035 \n gl_FragData[0] = vec4(float(idx % uint(256)) / 255.0,\
3036 \n float((idx / uint(256)) % uint(256)) / 255.0,\
3037 \n float((idx / uint(65536)) % uint(256)) / 255.0, 1.0);\
3038 \n }\
3039 \n else\
3040 \n {\
3041 \n gl_FragData[0] = vec4(0.0);\
3042 \n }\
3043 \n return;");
3044};
3045
3046//--------------------------------------------------------------------------
3047std::string PickingIdHigh24PassExit(
3048 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3049{
3050 return std::string("\
3051 \n // Special coloring mode which renders the voxel index in fragments that\
3052 \n // have accumulated certain level of opacity. Used during the selection\
3053 \n // pass vtkHardwareSelection::ID_MID24.\
3054 \n if (g_fragColor.a > 3.0/ 255.0)\
3055 \n {\
3056 \n uvec3 volumeDim = uvec3(in_textureExtentsMax - in_textureExtentsMin);\
3057 \n uvec3 voxelCoords = uvec3(volumeDim * g_dataPos);\
3058 \n // vtkHardwareSelector assumes index 0 to be empty space, so add uint(1).\
3059 \n uint idx = volumeDim.x * volumeDim.y * voxelCoords.z +\
3060 \n volumeDim.x * voxelCoords.y + voxelCoords.x + uint(1);\
3061 \n idx = ((idx & 0xff000000) >> 24);\
3062 \n gl_FragData[0] = vec4(float(idx % uint(256)) / 255.0,\
3063 \n float((idx / uint(256)) % uint(256)) / 255.0,\
3064 \n float(idx / uint(65536)) / 255.0, 1.0);\
3065 \n }\
3066 \n else\
3067 \n {\
3068 \n gl_FragData[0] = vec4(0.0);\
3069 \n }\
3070 \n return;");
3071};
3072
3073//--------------------------------------------------------------------------
3074std::string ShadingExit(vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper,
3075 vtkVolume* vtkNotUsed(vol), int noOfComponents, int independentComponents = 0)
3076{
3077 vtkOpenGLGPUVolumeRayCastMapper* glMapper = vtkOpenGLGPUVolumeRayCastMapper::SafeDownCast(mapper);
3078
3079 if (glMapper->GetUseDepthPass() &&
3082 {
3083 return std::string();
3084 }
3086 {
3087 if (noOfComponents > 1 && independentComponents)
3088 {
3089 return std::string("\
3090 \n g_srcColor = vec4(0);\
3091 \n for (int i = 0; i < in_noOfComponents; ++i)\
3092 \n {\
3093 \n vec4 tmp = computeColor(l_maxValue, computeOpacity(l_maxValue, i), i);\
3094 \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
3095 \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
3096 \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
3097 \n g_srcColor[3] += tmp[3] * in_componentWeight[i];\
3098 \n }\
3099 \n g_fragColor = g_srcColor;");
3100 }
3101 else
3102 {
3103 return std::string("\
3104 \n g_srcColor = computeColor(l_maxValue,\
3105 \n computeOpacity(l_maxValue));\
3106 \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
3107 \n g_fragColor.a = g_srcColor.a;");
3108 }
3109 }
3111 {
3112 if (noOfComponents > 1 && independentComponents)
3113 {
3114 return std::string("\
3115 \n g_srcColor = vec4(0);\
3116 \n for (int i = 0; i < in_noOfComponents; ++i)\
3117 \n {\
3118 \n vec4 tmp = computeColor(l_minValue, computeOpacity(l_minValue, i), i);\
3119 \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
3120 \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
3121 \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
3122 \n g_srcColor[2] += tmp[3] * tmp[3] * in_componentWeight[i];\
3123 \n }\
3124 \n g_fragColor = g_srcColor;");
3125 }
3126 else
3127 {
3128 return std::string("\
3129 \n g_srcColor = computeColor(l_minValue,\
3130 \n computeOpacity(l_minValue));\
3131 \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
3132 \n g_fragColor.a = g_srcColor.a;");
3134 }
3136 {
3137 if (noOfComponents > 1 && independentComponents)
3138 {
3139 return std::string("\
3140 \n for (int i = 0; i < in_noOfComponents; ++i)\
3141 \n {\
3142 \n if (l_numSamples[i] == uint(0))\
3143 \n {\
3144 \n continue;\
3145 \n }\
3146 \n l_avgValue[i] = l_avgValue[i] * in_componentWeight[i] /\
3147 \n l_numSamples[i];\
3148 \n if (i > 0)\
3149 \n {\
3150 \n l_avgValue[0] += l_avgValue[i];\
3151 \n }\
3152 \n }\
3153 \n l_avgValue[0] = clamp(l_avgValue[0], 0.0, 1.0);\
3154 \n g_fragColor = vec4(vec3(l_avgValue[0]), 1.0);");
3155 }
3156 else
3157 {
3158 return std::string("\
3159 \n if (l_numSamples.x == uint(0))\
3160 \n {\
3161 \n discard;\
3162 \n }\
3163 \n else\
3164 \n {\
3165 \n l_avgValue.x /= l_numSamples.x;\
3166 \n l_avgValue.x = clamp(l_avgValue.x, 0.0, 1.0);\
3167 \n g_fragColor = vec4(vec3(l_avgValue.x), 1.0);\
3168 \n }");
3169 }
3170 }
3171 else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
3172 {
3173 if (noOfComponents > 1 && independentComponents)
3174 {
3175 // Add all the components to get final color
3176 return std::string("\
3177 \n l_sumValue.x *= in_componentWeight.x;\
3178 \n for (int i = 1; i < in_noOfComponents; ++i)\
3179 \n {\
3180 \n l_sumValue.x += l_sumValue[i] * in_componentWeight[i];\
3181 \n }\
3182 \n l_sumValue.x = clamp(l_sumValue.x, 0.0, 1.0);\
3183 \n g_fragColor = vec4(vec3(l_sumValue.x), 1.0);");
3184 }
3185 else
3186 {
3187 return std::string("\
3188 \n l_sumValue.x = clamp(l_sumValue.x, 0.0, 1.0);\
3189 \n g_fragColor = vec4(vec3(l_sumValue.x), 1.0);");
3190 }
3191 }
3192 else
3193 {
3194 return std::string();
3195 }
3196}
3197
3198//--------------------------------------------------------------------------
3200 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3201{
3202 return std::string();
3203}
3204
3205//--------------------------------------------------------------------------
3207 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3208{
3209 return std::string("\
3210 \n const float g_opacityThreshold = 1.0 - 1.0 / 255.0;");
3211}
3212
3213//--------------------------------------------------------------------------
3214std::string PickingActorPassDeclaration(
3215 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3216{
3217 return std::string("\
3218 \n uniform vec3 in_propId;");
3219};
3220
3221//--------------------------------------------------------------------------
3222std::string TerminationInit(vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vol)
3223{
3224 std::string shaderStr;
3225 shaderStr += std::string("\
3226 \n // Flag to indicate if the raymarch loop should terminate \
3227 \n bool stop = false;\
3228 \n\
3229 \n g_terminatePointMax = 0.0;\
3230 \n\
3231 \n vec4 l_depthValue = texture2D(in_depthSampler, fragTexCoord);\
3232 \n // Depth test\
3233 \n if(gl_FragCoord.z >= l_depthValue.x)\
3234 \n {\
3235 \n discard;\
3236 \n }\
3237 \n\
3238 \n // color buffer or max scalar buffer have a reduced size.\
3239 \n fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
3240 \n in_inverseOriginalWindowSize;\
3241 \n");
3242
3244 {
3245 vtkImplicitFunction* sliceFunc = vol->GetProperty()->GetSliceFunction();
3246 if (sliceFunc)
3247 {
3248 if (sliceFunc->IsA("vtkPlane"))
3249 {
3250 shaderStr += std::string("\
3251 \n\
3252 \n // Intersection with plane\
3253 \n float t = intersectRayPlane(ip_vertexPos, rayDir);\
3254 \n vec4 intersection = vec4(ip_vertexPos + t * rayDir, 1.0);\
3255 \n g_intersection = (in_inverseTextureDatasetMatrix[0] * intersection).xyz;\
3256 \n vec4 intersDC = in_projectionMatrix * in_modelViewMatrix * in_volumeMatrix[0] * intersection;\
3257 \n intersDC.xyz /= intersDC.w;\
3258 \n vec4 intersWin = NDCToWindow(intersDC.x, intersDC.y, intersDC.z);\
3259 \n if(intersWin.z >= l_depthValue.x)\
3260 \n {\
3261 \n discard;\
3262 \n }\
3263 \n");
3264 }
3265 else
3266 {
3267 vtkErrorWithObjectMacro(
3268 sliceFunc, "Implicit function type is not supported by this mapper.");
3269 }
3270 }
3271 }
3272
3273 shaderStr += std::string("\
3274 \n // Compute max number of iterations it will take before we hit\
3275 \n // the termination point\
3276 \n\
3277 \n // Abscissa of the point on the depth buffer along the ray.\
3278 \n // point in texture coordinates\
3279 \n vec4 rayTermination = WindowToNDC(gl_FragCoord.x, gl_FragCoord.y, l_depthValue.x);\
3280 \n\
3281 \n // From normalized device coordinates to eye coordinates.\
3282 \n // in_projectionMatrix is inversed because of way VT\
3283 \n // From eye coordinates to texture coordinates\
3284 \n rayTermination = ip_inverseTextureDataAdjusted *\
3285 \n in_inverseVolumeMatrix[0] *\
3286 \n in_inverseModelViewMatrix *\
3287 \n in_inverseProjectionMatrix *\
3288 \n rayTermination;\
3289 \n g_rayTermination = rayTermination.xyz / rayTermination.w;\
3290 \n\
3291 \n // Setup the current segment:\
3292 \n g_dataPos = g_rayOrigin;\
3293 \n g_terminatePos = g_rayTermination;\
3294 \n\
3295 \n g_terminatePointMax = length(g_terminatePos.xyz - g_dataPos.xyz) /\
3296 \n length(g_dirStep);\
3297 \n g_currentT = 0.0;");
3298
3299 return shaderStr;
3300}
3301
3302//--------------------------------------------------------------------------
3303std::string TerminationImplementation(
3304 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3305{
3306 return std::string("\
3307 \n if(any(greaterThan(max(g_dirStep, vec3(0.0))*(g_dataPos - in_texMax[0]),vec3(0.0))) ||\
3308 \n any(greaterThan(min(g_dirStep, vec3(0.0))*(g_dataPos - in_texMin[0]),vec3(0.0))))\
3309 \n {\
3310 \n break;\
3311 \n }\
3312 \n\
3313 \n // Early ray termination\
3314 \n // if the currently composited colour alpha is already fully saturated\
3315 \n // we terminated the loop or if we have hit an obstacle in the\
3316 \n // direction of they ray (using depth buffer) we terminate as well.\
3317 \n if((g_fragColor.a > g_opacityThreshold) || \
3318 \n g_currentT >= g_terminatePointMax)\
3319 \n {\
3320 \n break;\
3321 \n }\
3322 \n ++g_currentT;");
3323}
3324
3325//--------------------------------------------------------------------------
3326std::string TerminationExit(
3327 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3328{
3329 return std::string();
3330}
3331
3332//--------------------------------------------------------------------------
3333std::string CroppingDeclarationVertex(
3334 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3335{
3336 return std::string();
3337}
3338
3339//--------------------------------------------------------------------------
3340std::string CroppingDeclarationFragment(
3341 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
3342{
3343 if (!mapper->GetCropping())
3344 {
3345 return std::string();
3346 }
3347
3348 return std::string("\
3349 \nuniform float in_croppingPlanes[6];\
3350 \nuniform int in_croppingFlags [32];\
3351 \nfloat croppingPlanesTexture[6];\
3352 \n\
3353 \n// X: axis = 0, Y: axis = 1, Z: axis = 2\
3354 \n// cp Cropping plane bounds (minX, maxX, minY, maxY, minZ, maxZ)\
3355 \nint computeRegionCoord(float cp[6], vec3 pos, int axis)\
3356 \n {\
3357 \n int cpmin = axis * 2;\
3358 \n int cpmax = cpmin + 1;\
3359 \n\
3360 \n if (pos[axis] < cp[cpmin])\
3361 \n {\
3362 \n return 1;\
3363 \n }\
3364 \n else if (pos[axis] >= cp[cpmin] &&\
3365 \n pos[axis] < cp[cpmax])\
3366 \n {\
3367 \n return 2;\
3368 \n }\
3369 \n else if (pos[axis] >= cp[cpmax])\
3370 \n {\
3371 \n return 3;\
3372 \n }\
3373 \n return 0;\
3374 \n }\
3375 \n\
3376 \nint computeRegion(float cp[6], vec3 pos)\
3377 \n {\
3378 \n return (computeRegionCoord(cp, pos, 0) +\
3379 \n (computeRegionCoord(cp, pos, 1) - 1) * 3 +\
3380 \n (computeRegionCoord(cp, pos, 2) - 1) * 9);\
3381 \n }");
3382}
3383
3384//--------------------------------------------------------------------------
3385std::string CroppingInit(
3386 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
3387{
3388 if (!mapper->GetCropping())
3389 {
3390 return std::string();
3391 }
3392
3393 return std::string("\
3394 \n // Convert cropping region to texture space\
3395 \n mat4 datasetToTextureMat = in_inverseTextureDatasetMatrix[0];\
3396 \n\
3397 \n vec4 tempCrop = vec4(in_croppingPlanes[0], 0.0, 0.0, 1.0);\
3398 \n tempCrop = datasetToTextureMat * tempCrop;\
3399 \n if (tempCrop[3] != 0.0)\
3400 \n {\
3401 \n tempCrop[0] /= tempCrop[3];\
3402 \n }\
3403 \n croppingPlanesTexture[0] = tempCrop[0];\
3404 \n\
3405 \n tempCrop = vec4(in_croppingPlanes[1], 0.0, 0.0, 1.0);\
3406 \n tempCrop = datasetToTextureMat * tempCrop;\
3407 \n if (tempCrop[3] != 0.0)\
3408 \n {\
3409 \n tempCrop[0] /= tempCrop[3];\
3410 \n }\
3411 \n croppingPlanesTexture[1] = tempCrop[0];\
3412 \n\
3413 \n tempCrop = vec4(0.0, in_croppingPlanes[2], 0.0, 1.0);\
3414 \n tempCrop = datasetToTextureMat * tempCrop;\
3415 \n if (tempCrop[3] != 0.0)\
3416 \n {\
3417 \n tempCrop[1] /= tempCrop[3];\
3418 \n }\
3419 \n croppingPlanesTexture[2] = tempCrop[1];\
3420 \n\
3421 \n tempCrop = vec4(0.0, in_croppingPlanes[3], 0.0, 1.0);\
3422 \n tempCrop = datasetToTextureMat * tempCrop;\
3423 \n if (tempCrop[3] != 0.0)\
3424 \n {\
3425 \n tempCrop[1] /= tempCrop[3];\
3426 \n }\
3427 \n croppingPlanesTexture[3] = tempCrop[1];\
3428 \n\
3429 \n tempCrop = vec4(0.0, 0.0, in_croppingPlanes[4], 1.0);\
3430 \n tempCrop = datasetToTextureMat * tempCrop;\
3431 \n if (tempCrop[3] != 0.0)\
3432 \n {\
3433 \n tempCrop[2] /= tempCrop[3];\
3434 \n }\
3435 \n croppingPlanesTexture[4] = tempCrop[2];\
3436 \n\
3437 \n tempCrop = vec4(0.0, 0.0, in_croppingPlanes[5], 1.0);\
3438 \n tempCrop = datasetToTextureMat * tempCrop;\
3439 \n if (tempCrop[3] != 0.0)\
3440 \n {\
3441 \n tempCrop[2] /= tempCrop[3];\
3442 \n }\
3443 \n croppingPlanesTexture[5] = tempCrop[2];");
3444}
3445
3446//--------------------------------------------------------------------------
3447std::string CroppingImplementation(
3448 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
3449{
3450 if (!mapper->GetCropping())
3451 {
3452 return std::string();
3453 }
3454
3455 return std::string("\
3456 \n // Determine region\
3457 \n int regionNo = computeRegion(croppingPlanesTexture, g_dataPos);\
3458 \n\
3459 \n // Do & operation with cropping flags\
3460 \n // Pass the flag that its Ok to sample or not to sample\
3461 \n if (in_croppingFlags[regionNo] == 0)\
3462 \n {\
3463 \n // Skip this voxel\
3464 \n g_skip = true;\
3465 \n }");
3466}
3467
3468//--------------------------------------------------------------------------
3469std::string CroppingExit(
3470 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3471{
3472 return std::string();
3473}
3474
3475//--------------------------------------------------------------------------
3476std::string ClippingDeclarationVertex(
3477 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3478{
3479 return std::string();
3480}
3481
3482//--------------------------------------------------------------------------
3483std::string ClippingDeclarationFragment(
3484 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
3485{
3486 if (!mapper->GetClippingPlanes())
3487 {
3488 return std::string();
3489 }
3490
3491 return std::string("\
3492 \n /// We support only 8 clipping planes for now\
3493 \n /// The first value is the size of the data array for clipping\
3494 \n /// planes (origin, normal)\
3495 \n uniform float in_clippingPlanes[49];\
3496 \n uniform float in_clippedVoxelIntensity;\
3497 \n\
3498 \n int clip_numPlanes;\
3499 \n vec3 clip_rayDirObj;\
3500 \n mat4 clip_texToObjMat;\
3501 \n mat4 clip_objToTexMat;\
3502 \n\
3503 \n// Tighten the sample range as needed to account for clip planes. \
3504 \n// Arguments are in texture coordinates. \
3505 \n// Returns true if the range is at all valid after clipping. If not, \
3506 \n// the fragment should be discarded. \
3507 \nbool AdjustSampleRangeForClipping(inout vec3 startPosTex, inout vec3 stopPosTex) \
3508 \n{ \
3509 \n vec4 startPosObj = vec4(0.0);\
3510 \n {\
3511 \n startPosObj = clip_texToObjMat * vec4(startPosTex - g_rayJitter, 1.0);\
3512 \n startPosObj = startPosObj / startPosObj.w;\
3513 \n startPosObj.w = 1.0;\
3514 \n }\
3515 \n\
3516 \n vec4 stopPosObj = vec4(0.0);\
3517 \n {\
3518 \n stopPosObj = clip_texToObjMat * vec4(stopPosTex, 1.0);\
3519 \n stopPosObj = stopPosObj / stopPosObj.w;\
3520 \n stopPosObj.w = 1.0;\
3521 \n }\
3522 \n\
3523 \n for (int i = 0; i < clip_numPlanes; i = i + 6)\
3524 \n {\
3525 \n vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\
3526 \n in_clippingPlanes[i + 2],\
3527 \n in_clippingPlanes[i + 3]);\
3528 \n vec3 planeNormal = normalize(vec3(in_clippingPlanes[i + 4],\
3529 \n in_clippingPlanes[i + 5],\
3530 \n in_clippingPlanes[i + 6]));\
3531 \n\
3532 \n // Abort if the entire segment is clipped:\
3533 \n // (We can do this before adjusting the term point, since it'll \
3534 \n // only move further into the clipped area)\
3535 \n float startDistance = dot(planeNormal, planeOrigin - startPosObj.xyz);\
3536 \n float stopDistance = dot(planeNormal, planeOrigin - stopPosObj.xyz);\
3537 \n bool startClipped = startDistance > 0.0;\
3538 \n bool stopClipped = stopDistance > 0.0;\
3539 \n if (startClipped && stopClipped)\
3540 \n {\
3541 \n return false;\
3542 \n }\
3543 \n\
3544 \n float rayDotNormal = dot(clip_rayDirObj, planeNormal);\
3545 \n bool frontFace = rayDotNormal > 0.0;\
3546 \n\
3547 \n // Move the start position further from the eye if needed:\
3548 \n if (frontFace && // Observing from the clipped side (plane's front face)\
3549 \n startDistance > 0.0) // Ray-entry lies on the clipped side.\
3550 \n {\
3551 \n // Scale the point-plane distance to the ray direction and update the\
3552 \n // entry point.\
3553 \n float rayScaledDist = startDistance / rayDotNormal;\
3554 \n startPosObj = vec4(startPosObj.xyz + rayScaledDist * clip_rayDirObj, 1.0);\
3555 \n vec4 newStartPosTex = clip_objToTexMat * vec4(startPosObj.xyz, 1.0);\
3556 \n newStartPosTex /= newStartPosTex.w;\
3557 \n startPosTex = newStartPosTex.xyz;\
3558 \n startPosTex += g_rayJitter;\
3559 \n }\
3560 \n\
3561 \n // Move the end position closer to the eye if needed:\
3562 \n if (!frontFace && // Observing from the unclipped side (plane's back face)\
3563 \n stopDistance > 0.0) // Ray-entry lies on the unclipped side.\
3564 \n {\
3565 \n // Scale the point-plane distance to the ray direction and update the\
3566 \n // termination point.\
3567 \n float rayScaledDist = stopDistance / rayDotNormal;\
3568 \n stopPosObj = vec4(stopPosObj.xyz + rayScaledDist * clip_rayDirObj, 1.0);\
3569 \n vec4 newStopPosTex = clip_objToTexMat * vec4(stopPosObj.xyz, 1.0);\
3570 \n newStopPosTex /= newStopPosTex.w;\
3571 \n stopPosTex = newStopPosTex.xyz;\
3572 \n }\
3573 \n }\
3574 \n\
3575 \n if (any(greaterThan(startPosTex, in_texMax[0])) ||\
3576 \n any(lessThan(startPosTex, in_texMin[0])))\
3577 \n {\
3578 \n return false;\
3579 \n }\
3580 \n\
3581 \n return true;\
3582 \n}\
3583 \n");
3584}
3585
3586//--------------------------------------------------------------------------
3587std::string ClippingInit(vtkRenderer* ren, vtkVolumeMapper* mapper, vtkVolume* vtkNotUsed(vol))
3588{
3589 if (!mapper->GetClippingPlanes())
3591 return std::string();
3592 }
3593
3594 std::string shaderStr;
3596 {
3597 shaderStr = std::string("\
3598 \n vec4 tempClip = in_volumeMatrix[0] * vec4(rayDir, 0.0);\
3599 \n if (tempClip.w != 0.0)\
3600 \n {\
3601 \n tempClip = tempClip/tempClip.w;\
3602 \n tempClip.w = 1.0;\
3603 \n }\
3604 \n clip_rayDirObj = normalize(tempClip.xyz);");
3605 }
3606 else
3607 {
3608 shaderStr = std::string("\
3609 clip_rayDirObj = normalize(in_projectionDirection);");
3611
3612 shaderStr += std::string("\
3613 \n clip_numPlanes = int(in_clippingPlanes[0]);\
3614 \n clip_texToObjMat = in_volumeMatrix[0] * in_textureDatasetMatrix[0];\
3615 \n clip_objToTexMat = in_inverseTextureDatasetMatrix[0] * in_inverseVolumeMatrix[0];\
3616 \n\
3617 \n // Adjust for clipping.\
3618 \n if (!AdjustSampleRangeForClipping(g_rayOrigin, g_rayTermination))\
3619 \n { // entire ray is clipped.\
3620 \n discard;\
3621 \n }\
3622 \n\
3623 \n // Update the segment post-clip:\
3624 \n g_dataPos = g_rayOrigin;\
3625 \n g_terminatePos = g_rayTermination;\
3626 \n g_terminatePointMax = length(g_terminatePos.xyz - g_dataPos.xyz) /\
3627 \n length(g_dirStep);\
3628 \n");
3629
3630 return shaderStr;
3632
3633//--------------------------------------------------------------------------
3634std::string ClippingImplementation(
3635 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3636{
3637 return std::string();
3638}
3639
3640//--------------------------------------------------------------------------
3641std::string ClippingExit(
3642 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3643{
3644 return std::string();
3645}
3646
3647//--------------------------------------------------------------------------
3648std::string BinaryMaskDeclaration(vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper),
3649 vtkVolume* vtkNotUsed(vol), vtkImageData* maskInput, vtkVolumeTexture* mask,
3650 int vtkNotUsed(maskType))
3651{
3652 if (!mask || !maskInput)
3653 {
3654 return std::string();
3655 }
3656 else
3657 {
3658 return std::string("uniform sampler3D in_mask;");
3659 }
3660}
3661
3662//--------------------------------------------------------------------------
3663std::string BinaryMaskImplementation(vtkRenderer* vtkNotUsed(ren),
3664 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), vtkImageData* maskInput,
3665 vtkVolumeTexture* mask, int maskType)
3666{
3667 if (!mask || !maskInput || maskType == vtkGPUVolumeRayCastMapper::LabelMapMaskType)
3668 {
3669 return std::string();
3670 }
3671 else
3672 {
3673 return std::string("\
3674 \nvec4 maskValue = texture3D(in_mask, g_dataPos);\
3675 \nif(maskValue.r <= 0.0)\
3676 \n {\
3677 \n g_skip = true;\
3678 \n }");
3679 }
3680}
3681
3682//--------------------------------------------------------------------------
3683std::string CompositeMaskDeclarationFragment(vtkRenderer* vtkNotUsed(ren),
3684 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), vtkImageData* maskInput,
3685 vtkVolumeTexture* mask, int maskType)
3686{
3687 if (!mask || !maskInput || maskType != vtkGPUVolumeRayCastMapper::LabelMapMaskType)
3688 {
3689 return std::string();
3690 }
3691 else
3692 {
3693 return std::string("\
3694 \nuniform float in_maskBlendFactor;\
3695 \nuniform sampler2D in_labelMapTransfer;\
3696 \nuniform float in_mask_scale;\
3697 \nuniform float in_mask_bias;\
3698 \nuniform int in_labelMapNumLabels;\
3699 \n");
3700 }
3701}
3702
3703//--------------------------------------------------------------------------
3704std::string CompositeMaskImplementation(vtkRenderer* vtkNotUsed(ren),
3705 vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol), vtkImageData* maskInput,
3706 vtkVolumeTexture* mask, int maskType, int noOfComponents)
3707{
3708 if (!mask || !maskInput || maskType != vtkGPUVolumeRayCastMapper::LabelMapMaskType)
3709 {
3710 return std::string();
3711 }
3712 else
3713 {
3714 std::string shaderStr = std::string("\
3715 \nvec4 scalar = texture3D(in_volume[0], g_dataPos);");
3716
3717 // simulate old intensity textures
3718 if (noOfComponents == 1)
3719 {
3720 shaderStr += std::string("\
3721 \n scalar.r = scalar.r * in_volume_scale[0].r + in_volume_bias[0].r;\
3722 \n scalar = vec4(scalar.r);");
3723 }
3724 else
3725 {
3726 // handle bias and scale
3727 shaderStr += std::string("\
3728 \n scalar = scalar * in_volume_scale[0] + in_volume_bias[0];");
3729 }
3730
3731 // Assumeing single component scalar for label texture lookup.
3732 // This can be extended to composite color obtained from all components
3733 // in the scalar array.
3734 return shaderStr + std::string("\
3735 \nif (in_maskBlendFactor == 0.0)\
3736 \n {\
3737 \n g_srcColor.a = computeOpacity(scalar);\
3738 \n if (g_srcColor.a > 0)\
3739 \n {\
3740 \n g_srcColor = computeColor(scalar, g_srcColor.a);\
3741 \n }\
3742 \n }\
3743 \nelse\
3744 \n {\
3745 \n float opacity = computeOpacity(scalar);\
3746 \n // Get the mask value at this same location\
3747 \n vec4 maskValue = texture3D(in_mask, g_dataPos);\
3748 \n maskValue.r = maskValue.r * in_mask_scale + in_mask_bias;\
3749 \n // Quantize the height of the labelmap texture over number of labels\
3750 \n if (in_labelMapNumLabels > 0)\
3751 \n {\
3752 \n maskValue.r =\
3753 \n floor(maskValue.r * in_labelMapNumLabels) /\
3754 \n in_labelMapNumLabels;\
3755 \n }\
3756 \n else\
3757 \n {\
3758 \n maskValue.r = 0.0;\
3759 \n }\
3760 \n if(maskValue.r == 0.0)\
3761 \n {\
3762 \n g_srcColor.a = opacity;\
3763 \n if (g_srcColor.a > 0)\
3764 \n {\
3765 \n g_srcColor = computeColor(scalar, g_srcColor.a);\
3766 \n }\
3767 \n }\
3768 \n else\
3769 \n {\
3770 \n g_srcColor = texture2D(in_labelMapTransfer,\
3771 \n vec2(scalar.r, maskValue.r));\
3772 \n if (g_srcColor.a > 0)\
3773 \n {\
3774 \n g_srcColor = computeLighting(g_srcColor, 0, maskValue.r);\
3775 \n }\
3776 \n if (in_maskBlendFactor < 1.0)\
3777 \n {\
3778 \n vec4 color = opacity > 0 ? computeColor(scalar, opacity) : vec4(0);\
3779 \n g_srcColor = (1.0 - in_maskBlendFactor) * color +\
3780 \n in_maskBlendFactor * g_srcColor;\
3781 \n }\
3782 \n }\
3783 \n }");
3784 }
3785}
3786
3787//--------------------------------------------------------------------------
3789 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3791 return std::string("uniform bool in_clampDepthToBackface;\n"
3792 "vec3 l_opaqueFragPos;\n"
3793 "bool l_updateDepth;\n");
3794}
3795
3796//--------------------------------------------------------------------------
3797std::string RenderToImageInit(
3798 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3799{
3800 return std::string("\
3801 \n l_opaqueFragPos = vec3(-1.0);\
3802 \n if(in_clampDepthToBackface)\
3803 \n {\
3804 \n l_opaqueFragPos = g_dataPos;\
3805 \n }\
3806 \n l_updateDepth = true;");
3807}
3808
3809//--------------------------------------------------------------------------
3810std::string RenderToImageImplementation(
3811 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3812{
3813 return std::string("\
3814 \n if(!g_skip && g_srcColor.a > 0.0 && l_updateDepth)\
3815 \n {\
3816 \n l_opaqueFragPos = g_dataPos;\
3817 \n l_updateDepth = false;\
3818 \n }");
3819}
3820
3821//--------------------------------------------------------------------------
3822std::string RenderToImageExit(
3823 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3824{
3825 return std::string("\
3826 \n if (l_opaqueFragPos == vec3(-1.0))\
3827 \n {\
3828 \n gl_FragData[1] = vec4(1.0);\
3829 \n }\
3830 \n else\
3831 \n {\
3832 \n vec4 depthValue = in_projectionMatrix * in_modelViewMatrix *\
3833 \n in_volumeMatrix[0] * in_textureDatasetMatrix[0] *\
3834 \n vec4(l_opaqueFragPos, 1.0);\
3835 \n depthValue /= depthValue.w;\
3836 \n gl_FragData[1] = vec4(vec3(0.5 * (gl_DepthRange.far -\
3837 \n gl_DepthRange.near) * depthValue.z + 0.5 *\
3838 \n (gl_DepthRange.far + gl_DepthRange.near)), 1.0);\
3839 \n }");
3840}
3841
3842//--------------------------------------------------------------------------
3843std::string DepthPassInit(
3844 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3845{
3846 return std::string("\
3847 \n vec3 l_isoPos = g_dataPos;");
3848}
3849
3850//--------------------------------------------------------------------------
3851std::string DepthPassImplementation(
3852 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3853{
3854 return std::string("\
3855 \n if(!g_skip && g_srcColor.a > 0.0)\
3856 \n {\
3857 \n l_isoPos = g_dataPos;\
3858 \n g_exit = true; g_skip = true;\
3859 \n }");
3860}
3861
3862//--------------------------------------------------------------------------
3863std::string DepthPassExit(
3864 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3865{
3866 return std::string("\
3867 \n vec4 depthValue = in_projectionMatrix * in_modelViewMatrix *\
3868 \n in_volumeMatrix[0] * in_textureDatasetMatrix[0] *\
3869 \n vec4(l_isoPos, 1.0);\
3870 \n gl_FragData[0] = vec4(l_isoPos, 1.0);\
3871 \n gl_FragData[1] = vec4(vec3((depthValue.z/depthValue.w) * 0.5 + 0.5),\
3872 \n 1.0);");
3873}
3874
3875//---------------------------------------------------------------------------
3876std::string WorkerImplementation(
3877 vtkRenderer* vtkNotUsed(ren), vtkVolumeMapper* vtkNotUsed(mapper), vtkVolume* vtkNotUsed(vol))
3878{
3879 return std::string("\
3880 \n initializeRayCast();\
3881 \n castRay(-1.0, -1.0);\
3882 \n finalizeRayCast();");
3883}
3884
3885//---------------------------------------------------------------------------
3886std::string ImageSampleDeclarationFrag(
3887 const std::vector<std::string>& varNames, const size_t usedNames)
3888{
3889 std::string shader = "\n";
3890 for (size_t i = 0; i < usedNames; i++)
3891 {
3892 shader += "uniform sampler2D " + varNames[i] + ";\n";
3893 }
3894 return shader;
3895}
3896
3897//---------------------------------------------------------------------------
3899 const std::vector<std::string>& varNames, const size_t usedNames)
3900{
3901 std::string shader = "\n";
3902 for (size_t i = 0; i < usedNames; i++)
3903 {
3904 std::stringstream ss;
3905 ss << i;
3906 shader += " gl_FragData[" + ss.str() + "] = texture2D(" + varNames[i] + ", texCoord);\n";
3907 }
3908 shader += " return;\n";
3909 return shader;
3910}
3911}
3912
3913#endif // vtkVolumeShaderComposer_h
3914// 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)
int GetInputCount()
Number of currently active ports.
virtual float GetVolumetricScatteringBlending()
This parameter controls the blending between surfacic approximation and volumetric multi-scattering.
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:67
vtkCamera * GetActiveCamera()
Get the current camera.
Hold a reference to a vtkObjectBase instance.
Abstract class for a volume mapper.
virtual bool GetComputeNormalFromOpacity()
If enabled, the volume(s) whose shading is enabled will use the gradient of opacity instead of the sc...
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 float GetScatteringAnisotropy()
Get/Set the volume's scattering anisotropy.
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.
represents a volume (data & properties) in a rendered scene
Definition vtkVolume.h:45
virtual vtkVolumeProperty * GetProperty()
Set/Get the volume property.
@ position
Definition vtkX3D.h:267
@ 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 ComputeDensityGradientDeclaration(vtkOpenGLGPUVolumeRayCastMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int noOfComponents, int independentComponents, int useGradYAxis)
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 CroppingDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string ComputeLightingDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents, int totalNumberOfLights, int numberPositionalLights, bool defaultLighting)
std::string PhaseFunctionDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *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 ComputeMatricesInit(vtkOpenGLGPUVolumeRayCastMapper *vtkNotUsed(mapper), int numberPositionalLights)
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 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 BaseDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int totalNumberOfLights, int numberPositionalLights, bool defaultLighting, int noOfComponents, int independentComponents)
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 ComputeColorUniforms(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int noOfComponents, vtkVolumeProperty *volProp)
std::string ComputeRayDirectionDeclaration(vtkRenderer *ren, vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int vtkNotUsed(noOfComponents))
std::string BaseInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, bool defaultLighting)
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 ComputeRGBA2DWithGradientDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, std::map< int, std::string > opacityTableMap, int useGradient)
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 ComputeLightingMultiDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents, int vtkNotUsed(totalNumberOfLights), bool defaultLighting)
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 ComputeOpacityEvaluationCall(vtkOpenGLGPUVolumeRayCastMapper *vtkNotUsed(mapper), vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int noOfComponents, int independentComponents, int useGradYAxis, std::string position, bool requestColor=false)
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 ComputeVolumetricShadowDec(vtkOpenGLGPUVolumeRayCastMapper *mapper, vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int useGradYAxis)