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