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