4 #ifndef vtkVolumeShaderComposer_h
5 #define vtkVolumeShaderComposer_h
28 for (
auto& item : inputs)
41 for (
auto& item : inputs)
44 const bool lighting = volProp->
GetShade() == 1;
53 for (
auto& item : inputs)
57 if (useClippedVoxelIntensity)
67 return arrayName.substr(0, arrayName.length() - 3);
79 VTK_ABI_NAMESPACE_BEGIN
85 " //Transform vertex (data coordinates) to clip coordinates\n"
86 " // p_clip = T_ProjViewModel * T_dataToWorld * p_data\n"
87 " vec4 pos = in_projectionMatrix * in_modelViewMatrix * in_volumeMatrix[0] *\n"
88 " vec4(in_vertexPos.xyz, 1.0);\n"
89 " gl_Position = pos;\n");
97 " // Transform vertex (data coordinates) to texture coordinates.\n"
98 " // p_texture = T_dataToTex * p_data\n"
99 " vec3 uvx = sign(in_cellSpacing[0]) * (in_inverseTextureDatasetMatrix[0] *\n"
100 " vec4(in_vertexPos, 1.0)).xyz;\n"
102 " // For point dataset, we offset the texture coordinate\n"
103 " // to account for OpenGL treating voxel at the center of the cell.\n"
104 " // Transform cell tex-coordinates to point tex-coordinates (cellToPoint\n"
105 " // is an identity matrix in the case of cell data).\n"
106 " ip_textureCoords = (in_cellToPoint[0] * vec4(uvx, 1.0)).xyz;\n"
107 " ip_inverseTextureDataAdjusted = in_cellToPoint[0] * in_inverseTextureDatasetMatrix[0];\n");
112 vtkVolume* vtkNotUsed(vol),
bool multipleInputs)
115 const int numInputs = gpuMapper->GetInputCount();
117 std::ostringstream ss;
118 ss <<
"uniform vec3 in_cellSpacing[" << numInputs
120 "uniform mat4 in_modelViewMatrix;\n"
121 "uniform mat4 in_projectionMatrix;\n";
123 const int numTransf = multipleInputs ? numInputs + 1 : 1;
124 ss <<
"uniform mat4 in_volumeMatrix[" << numTransf
126 "uniform mat4 in_inverseTextureDatasetMatrix["
129 "uniform mat4 in_cellToPoint["
133 "//This variable could be 'invariant varying' but it is declared\n"
134 "//as 'varying' to avoid compiler compatibility issues.\n"
135 "out mat4 ip_inverseTextureDataAdjusted;\n";
143 int numberPositionalLights,
bool defaultLighting,
int noOfComponents,
int independentComponents)
145 const int numInputs =
static_cast<int>(inputs.size());
147 std::ostringstream toShaderStr;
148 toShaderStr <<
"uniform sampler3D in_volume[" << numInputs <<
"];\n";
150 toShaderStr <<
"uniform vec4 in_volume_scale[" << numInputs
152 "uniform vec4 in_volume_bias["
153 << numInputs <<
"];\n";
157 toShaderStr <<
"uniform sampler1D in_coordTexs;\n";
158 toShaderStr <<
"uniform vec3 in_coordTexSizes;\n";
159 toShaderStr <<
"uniform vec3 in_coordsScale;\n";
160 toShaderStr <<
"uniform vec3 in_coordsBias;\n";
165 toShaderStr <<
"uniform sampler3D in_blanking;\n";
168 toShaderStr <<
"uniform int in_noOfComponents;\n"
170 "uniform sampler2D in_depthSampler;\n";
175 toShaderStr <<
"uniform sampler2D in_noiseSampler;\n";
180 const int numTransf = (numInputs > 1) ? numInputs + 1 : 1;
181 toShaderStr <<
"uniform mat4 in_volumeMatrix[" << numTransf
183 "uniform mat4 in_inverseVolumeMatrix["
186 "uniform mat4 in_textureDatasetMatrix["
189 "uniform mat4 in_inverseTextureDatasetMatrix["
192 "uniform mat4 in_textureToEye["
195 "uniform vec3 in_texMin["
198 "uniform vec3 in_texMax["
201 "// Eye position in dataset space\n"
202 "uniform vec3 in_eyePosObjs["
205 "uniform mat4 in_cellToPoint["
206 << numTransf <<
"];\n";
208 toShaderStr <<
"// view and model matrices\n"
209 "uniform mat4 in_projectionMatrix;\n"
210 "uniform mat4 in_inverseProjectionMatrix;\n"
211 "uniform mat4 in_modelViewMatrix;\n"
212 "uniform mat4 in_inverseModelViewMatrix;\n"
213 "in mat4 ip_inverseTextureDataAdjusted;\n"
216 "uniform vec3 in_cellStep["
217 << numInputs <<
"];\n";
222 toShaderStr <<
"mat4 g_eyeToTexture = in_inverseTextureDatasetMatrix[0] *"
223 " in_inverseVolumeMatrix[0] * in_inverseModelViewMatrix;\n";
226 toShaderStr <<
"mat4 g_texToView;\n";
228 toShaderStr <<
"uniform vec2 in_scalarsRange[" << numInputs * 4
230 "uniform vec3 in_cellSpacing["
234 "// Sample distance\n"
235 "uniform float in_sampleDistance;\n"
238 "uniform vec2 in_windowLowerLeftCorner;\n"
239 "uniform vec2 in_inverseOriginalWindowSize;\n"
240 "uniform vec2 in_inverseWindowSize;\n"
241 "uniform vec3 in_textureExtentsMax;\n"
242 "uniform vec3 in_textureExtentsMin;\n"
244 "// Material and lighting\n"
245 "uniform vec3 in_diffuse[4];\n"
246 "uniform vec3 in_ambient[4];\n"
247 "uniform vec3 in_specular[4];\n"
248 "uniform float in_shininess[4];\n"
251 "vec3 g_rayJitter = vec3(0.0);\n"
253 "uniform vec2 in_averageIPRange;\n";
255 const bool hasGradientOpacity = HasGradientOpacity(inputs);
256 if (totalNumberOfLights > 0 || hasGradientOpacity)
258 toShaderStr <<
"uniform bool in_twoSidedLighting;\n";
263 toShaderStr << R
"***(
264 uniform float in_giReach;
265 uniform float in_anisotropy;
266 uniform float in_volumetricScatteringBlending;
271 if (totalNumberOfLights > 0)
276 if (!defaultLighting)
278 toShaderStr <<
"#define TOTAL_NUMBER_LIGHTS " << totalLights
280 "#define NUMBER_POS_LIGHTS "
283 "vec4 g_fragWorldPos;\n"
284 "uniform vec3 in_lightAmbientColor[TOTAL_NUMBER_LIGHTS];\n"
285 "uniform vec3 in_lightDiffuseColor[TOTAL_NUMBER_LIGHTS];\n"
286 "uniform vec3 in_lightSpecularColor[TOTAL_NUMBER_LIGHTS];\n"
287 "uniform vec3 in_lightDirection[TOTAL_NUMBER_LIGHTS];\n";
288 if (numberPositionalLights > 0)
290 toShaderStr <<
"uniform vec3 in_lightPosition[NUMBER_POS_LIGHTS];\n"
291 "uniform vec3 in_lightAttenuation[NUMBER_POS_LIGHTS];\n"
292 "uniform float in_lightConeAngle[NUMBER_POS_LIGHTS];\n"
293 "uniform float in_lightExponent[NUMBER_POS_LIGHTS];\n";
298 toShaderStr <<
"vec3 g_lightDirectionTex[TOTAL_NUMBER_LIGHTS];\n";
300 if (numberPositionalLights > 0)
302 toShaderStr <<
"vec3 g_lightPositionTex[NUMBER_POS_LIGHTS];\n";
308 toShaderStr <<
"uniform vec3 in_lightAmbientColor[1];\n"
309 "uniform vec3 in_lightDiffuseColor[1];\n"
310 "uniform vec3 in_lightSpecularColor[1];\n"
311 "vec4 g_lightPosObj["
321 << numInputs <<
"];\n";
325 if (noOfComponents > 1 && independentComponents)
327 toShaderStr <<
"uniform vec4 in_componentWeight;\n";
333 toShaderStr <<
"uniform sampler2D in_depthPassSampler;\n";
338 toShaderStr <<
"#if NUMBER_OF_CONTOURS\n"
339 "uniform float in_isosurfacesValues[NUMBER_OF_CONTOURS];\n"
341 "int findIsoSurfaceIndex(float scalar, float array[NUMBER_OF_CONTOURS+2])\n"
343 " int index = NUMBER_OF_CONTOURS >> 1;\n"
344 " while (scalar > array[index]) ++index;\n"
345 " while (scalar < array[index]) --index;\n"
352 vtkVolume* vol = inputs.begin()->second.Volume;
355 if (func && func->
IsA(
"vtkPlane"))
358 <<
"uniform vec3 in_slicePlaneOrigin;\n"
359 "uniform vec3 in_slicePlaneNormal;\n"
360 "vec3 g_intersection;\n"
362 "float intersectRayPlane(vec3 rayOrigin, vec3 rayDir)\n"
364 " vec4 planeNormal = in_inverseVolumeMatrix[0] * vec4(in_slicePlaneNormal, 0.0);\n"
365 " float denom = dot(planeNormal.xyz, rayDir);\n"
366 " if (abs(denom) > 1e-6)\n"
368 " vec4 planeOrigin = in_inverseVolumeMatrix[0] * vec4(in_slicePlaneOrigin, 1.0);\n"
369 " return dot(planeOrigin.xyz - rayOrigin, planeNormal.xyz) / denom;\n"
376 return toShaderStr.str();
384 vtkVolume* vol = inputs.begin()->second.Volume;
385 const int numInputs =
static_cast<int>(inputs.size());
387 std::ostringstream shaderStr;
393 \n vec2 fragTexCoord2 = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
394 \n in_inverseWindowSize;\
395 \n vec4 depthValue = texture2D(in_depthPassSampler, fragTexCoord2);\
396 \n vec4 rayOrigin = WindowToNDC(gl_FragCoord.x, gl_FragCoord.y, depthValue.x);\
398 \n // From normalized device coordinates to eye coordinates.\
399 \n // in_projectionMatrix is inversed because of way VT\
400 \n // From eye coordinates to texture coordinates\
401 \n rayOrigin = in_inverseTextureDatasetMatrix[0] *\
402 \n in_inverseVolumeMatrix[0] *\
403 \n in_inverseModelViewMatrix *\
404 \n in_inverseProjectionMatrix *\
406 \n rayOrigin /= rayOrigin.w;\
407 \n g_rayOrigin = rayOrigin.xyz;";
412 \n // Get the 3D texture coordinates for lookup into the in_volume dataset\
413 \n g_rayOrigin = ip_textureCoords.xyz;";
417 \n // Getting the ray marching direction (in dataset space)\
418 \n vec3 rayDir = computeRayDirection();\
420 \n // 2D Texture fragment coordinates [0,1] from fragment coordinates.\
421 \n // The frame buffer texture has the size of the plain buffer but \
422 \n // we use a fraction of it. The texture coordinate is less than 1 if\
423 \n // the reduction factor is less than 1.\
424 \n // Device coordinates are between -1 and 1. We need texture\
425 \n // coordinates between 0 and 1. The in_depthSampler\
426 \n // buffer has the original size buffer.\
427 \n vec2 fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
428 \n in_inverseWindowSize;\
430 \n // Multiply the raymarching direction with the step size to get the\
431 \n // sub-step size we need to take at each raymarching step\
432 \n g_dirStep = (ip_inverseTextureDataAdjusted *\
433 \n vec4(rayDir, 0.0)).xyz * in_sampleDistance;\
434 \n g_lengthStep = length(g_dirStep);\
438 \n float jitterValue = 0.0;\
447 \n jitterValue = texture2D(in_noiseSampler, gl_FragCoord.xy /\
448 vec2(textureSize(in_noiseSampler, 0))).x;\
449 \n g_rayJitter = g_dirStep * jitterValue;\
455 \n g_rayJitter = g_dirStep;\
459 \n g_rayOrigin += g_rayJitter;\
464 \n // Flag to determine if voxel should be considered for the rendering\
470 \n // Light position in dataset space";
471 for (
int i = 0; i < numInputs; ++i)
476 << i <<
"] = vec4(in_eyePosObjs[" << (numInputs > 1 ? i + 1 : i) <<
"], 1.0);\
478 << i <<
"] = normalize(g_lightPosObj[" << i <<
"].xyz - ip_vertexPos);\
480 << i <<
"] = normalize(in_eyePosObjs[" << i <<
"].xyz - ip_vertexPos);\
482 << i <<
"] = normalize(g_ldir[" << i <<
"] + g_vdir[" << i <<
"]);";
486 return shaderStr.str();
496 \n g_skip = false;");
502 if (blankPoints || blankCells)
505 \n // Check whether the neighboring points/cells are blank.\
506 \n // Note the half cellStep because texels are point centered.\
507 \n vec3 xvec = vec3(in_cellStep[0].x/2.0, 0.0, 0.0);\
508 \n vec3 yvec = vec3(0.0, in_cellStep[0].y/2.0, 0.0);\
509 \n vec3 zvec = vec3(0.0, 0.0, in_cellStep[0].z/2.0);\
510 \n vec3 texPosPVec[3];\
511 \n texPosPVec[0] = g_dataPos + xvec;\
512 \n texPosPVec[1] = g_dataPos + yvec;\
513 \n texPosPVec[2] = g_dataPos + zvec;\
514 \n vec3 texPosNVec[3];\
515 \n texPosNVec[0] = g_dataPos - xvec;\
516 \n texPosNVec[1] = g_dataPos - yvec;\
517 \n texPosNVec[2] = g_dataPos - zvec;\
518 \n vec4 blankValue = texture3D(in_blanking, g_dataPos);\
519 \n vec4 blankValueXP = texture3D(in_blanking, texPosPVec[0]);\
520 \n vec4 blankValueYP = texture3D(in_blanking, texPosPVec[1]);\
521 \n vec4 blankValueZP = texture3D(in_blanking, texPosPVec[2]);\
522 \n vec4 blankValueXN = texture3D(in_blanking, texPosNVec[0]);\
523 \n vec4 blankValueYN = texture3D(in_blanking, texPosNVec[1]);\
524 \n vec4 blankValueZN = texture3D(in_blanking, texPosNVec[2]);\
525 \n vec3 blankValuePx;\
526 \n blankValuePx[0] = blankValueXP.x;\
527 \n blankValuePx[1] = blankValueYP.x;\
528 \n blankValuePx[2] = blankValueZP.x;\
529 \n vec3 blankValuePy;\
530 \n blankValuePy[0] = blankValueXP.y;\
531 \n blankValuePy[1] = blankValueYP.y;\
532 \n blankValuePy[2] = blankValueZP.y;\
533 \n vec3 blankValueNx;\
534 \n blankValueNx[0] = blankValueXN.x;\
535 \n blankValueNx[1] = blankValueYN.x;\
536 \n blankValueNx[2] = blankValueZN.x;\
537 \n vec3 blankValueNy;\
538 \n blankValueNy[0] = blankValueXN.y;\
539 \n blankValueNy[1] = blankValueYN.y;\
540 \n blankValueNy[2] = blankValueZN.y;\
545 \n // If the current or neighboring points\
546 \n // (that belong to cells that share this texel) are blanked,\
547 \n // skip the texel. In other words, if point 1 were blank,\
548 \n // texels 0, 1 and 2 would have to be skipped.\
549 \n if (blankValue.x > 0.0 ||\
550 \n any(greaterThan(blankValueNx, vec3(0.0))) ||\
551 \n any(greaterThan(blankValuePx, vec3(0.0))))\
553 \n // skip this texel\
560 \n // If the current or previous cells (that share this texel)\
561 \n // are blanked, skip the texel. In other words, if cell 1\
562 \n // is blanked, texels 1 and 2 would have to be skipped.\
563 \n else if (blankValue.y > 0.0 ||\
564 \n any(greaterThan(blankValuePy, vec3(0.0))) ||\
565 \n any(greaterThan(blankValueNy, vec3(0.0))))\
567 \n // skip this texel\
576 \n // If the current or previous cells (that share this texel)\
577 \n // are blanked, skip the texel. In other words, if cell 1\
578 \n // is blanked, texels 1 and 2 would have to be skipped.\
579 \n if (blankValue.x > 0.0 ||\
580 \n any(greaterThan(blankValueNx, vec3(0.0))) ||\
581 \n any(greaterThan(blankValuePx, vec3(0.0))))\
583 \n // skip this texel\
593 \n g_dataPos = g_intersection;\
609 int independentComponents, std::map<int, std::string> gradientTableMap)
612 std::ostringstream ss;
613 if (volProperty->HasGradientOpacity())
615 ss <<
"uniform sampler2D " << ArrayBaseName(gradientTableMap[0]) <<
"[" << noOfComponents
618 bool useLabelGradientOpacity =
619 (volProperty->HasLabelGradientOpacity() && (noOfComponents == 1 || !independentComponents));
620 if (useLabelGradientOpacity)
622 ss <<
"uniform sampler2D in_labelMapGradientOpacity;\n";
627 if (volProperty->HasGradientOpacity() && noOfComponents > 0)
629 if (noOfComponents == 1 || !independentComponents)
632 \nfloat computeGradientOpacity(vec4 grad)\
634 \n return texture2D(" +
635 gradientTableMap[0] +
", vec2(grad.w, 0.0)).r;\
641 \nfloat computeGradientOpacity(vec4 grad, int component)\
644 for (
int i = 0; i < noOfComponents; ++i)
646 std::ostringstream toString;
649 \n if (component == " +
650 toString.str() +
")");
654 \n return texture2D(" +
655 gradientTableMap[i] +
", vec2(grad.w, 0.0)).r;\
664 if (useLabelGradientOpacity)
667 \nfloat computeGradientOpacityForLabel(vec4 grad, float label)\
669 \n return texture2D(in_labelMapGradientOpacity, vec2(grad.w, label)).r;\
680 const bool hasLighting = HasLighting(inputs);
681 const bool hasGradientOp = HasGradientOpacity(inputs);
684 if (hasLighting || hasGradientOp)
687 "// c is short for component\n"
688 "vec4 computeGradient(in vec3 texPos, in int c, in sampler3D volume,in int index)\n"
690 " // Approximate Nabla(F) derivatives with central differences.\n"
691 " vec3 g1; // F_front\n"
692 " vec3 g2; // F_back\n"
693 " vec3 xvec = vec3(in_cellStep[index].x, 0.0, 0.0);\n"
694 " vec3 yvec = vec3(0.0, in_cellStep[index].y, 0.0);\n"
695 " vec3 zvec = vec3(0.0, 0.0, in_cellStep[index].z);\n"
696 " vec3 texPosPvec[3];\n"
697 " texPosPvec[0] = texPos + xvec;\n"
698 " texPosPvec[1] = texPos + yvec;\n"
699 " texPosPvec[2] = texPos + zvec;\n"
700 " vec3 texPosNvec[3];\n"
701 " texPosNvec[0] = texPos - xvec;\n"
702 " texPosNvec[1] = texPos - yvec;\n"
703 " texPosNvec[2] = texPos - zvec;\n"
704 " g1.x = texture3D(volume, vec3(texPosPvec[0]))[c];\n"
705 " g1.y = texture3D(volume, vec3(texPosPvec[1]))[c];\n"
706 " g1.z = texture3D(volume, vec3(texPosPvec[2]))[c];\n"
707 " g2.x = texture3D(volume, vec3(texPosNvec[0]))[c];\n"
708 " g2.y = texture3D(volume, vec3(texPosNvec[1]))[c];\n"
709 " g2.z = texture3D(volume, vec3(texPosNvec[2]))[c];\n"
714 std::string(
" vec4 g1ObjDataPos[3], g2ObjDataPos[3];\n"
715 " for (int i = 0; i < 3; ++i)\n"
717 " g1ObjDataPos[i] = clip_texToObjMat * vec4(texPosPvec[i], 1.0);\n"
718 " if (g1ObjDataPos[i].w != 0.0)\n"
720 " g1ObjDataPos[i] /= g1ObjDataPos[i].w;\n"
722 " g2ObjDataPos[i] = clip_texToObjMat * vec4(texPosNvec[i], 1.0);\n"
723 " if (g2ObjDataPos[i].w != 0.0)\n"
725 " g2ObjDataPos[i] /= g2ObjDataPos[i].w;\n"
729 " for (int i = 0; i < clip_numPlanes && !g_skip; i = i + 6)\n"
731 " vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\n"
732 " in_clippingPlanes[i + 2],\n"
733 " in_clippingPlanes[i + 3]);\n"
734 " vec3 planeNormal = normalize(vec3(in_clippingPlanes[i + 4],\n"
735 " in_clippingPlanes[i + 5],\n"
736 " in_clippingPlanes[i + 6]));\n"
737 " for (int j = 0; j < 3; ++j)\n"
739 " if (dot(vec3(planeOrigin - g1ObjDataPos[j].xyz), planeNormal) > 0)\n"
741 " g1[j] = in_clippedVoxelIntensity;\n"
743 " if (dot(vec3(planeOrigin - g2ObjDataPos[j].xyz), planeNormal) > 0)\n"
745 " g2[j] = in_clippedVoxelIntensity;\n"
751 shaderStr +=
std::string(
" // Apply scale and bias to the fetched values.\n"
752 " g1 = g1 * in_volume_scale[index][c] + in_volume_bias[index][c];\n"
753 " g2 = g2 * in_volume_scale[index][c] + in_volume_bias[index][c];\n"
758 std::string(
" // Central differences: (F_front - F_back) / 2h\n"
759 " // This version of computeGradient() is only used for lighting\n"
760 " // calculations (only direction matters), hence the difference is\n"
761 " // not scaled by 2h and a dummy gradient mag is returned (-1.).\n"
762 " return vec4((g1 - g2) / in_cellSpacing[index], -1.0);\n"
768 " // Scale values the actual scalar range.\n"
769 " float range = in_scalarsRange[4*index+c][1] - in_scalarsRange[4*index+c][0];\n"
770 " g1 = in_scalarsRange[4*index+c][0] + range * g1;\n"
771 " g2 = in_scalarsRange[4*index+c][0] + range * g2;\n"
773 " // Central differences: (F_front - F_back) / 2h\n"
776 " float avgSpacing = (in_cellSpacing[index].x +\n"
777 " in_cellSpacing[index].y + in_cellSpacing[index].z) / 3.0;\n"
778 " vec3 aspect = in_cellSpacing[index] * 2.0 / avgSpacing;\n"
780 " float grad_mag = length(g2);\n"
782 " // Handle normalizing with grad_mag == 0.0\n"
783 " g2 = grad_mag > 0.0 ? normalize(g2) : vec3(0.0);\n"
785 " // Since the actual range of the gradient magnitude is unknown,\n"
786 " // assume it is in the range [0, 0.25 * dataRange].\n"
787 " range = range != 0.0 ? range : 1.0;\n"
788 " grad_mag = grad_mag / (0.25 * range);\n"
789 " grad_mag = clamp(grad_mag, 0.0, 1.0);\n"
791 " return vec4(g2.xyz, grad_mag);\n"
798 "vec4 computeGradient(in vec3 texPos, in int c, in sampler3D volume, in int index)\n"
800 " return vec4(0.0);\n"
813 for(int i=0; i<TOTAL_NUMBER_LIGHTS; i++)
815 g_lightDirectionTex[i] = (g_eyeToTexture * vec4(-in_lightDirection[i], 0.0)).xyz;
819 if (numberPositionalLights > 0)
822 for(int i=0; i<NUMBER_POS_LIGHTS; i++)
824 g_lightPositionTex[i] = (g_eyeToTexture * vec4(in_lightPosition[i], 1.0)).xyz;
834 int independentComponents, std::map<int, std::string> opacityTableMap,
int useGradient)
838 bool severalIndpt = noOfComponents > 1 && independentComponents;
840 ?
"vec4 computeRGBAWithGrad(vec4 scalar, vec4 grad, int component)\n"
841 :
"vec4 computeRGBAWithGrad(vec4 scalar, vec4 grad)\n";
850 "vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
851 "for (int i = 0; i < 4; ++i)\n"
853 " yscalar[i] = yscalar[i] * in_transfer2DYAxis_scale[i] + in_transfer2DYAxis_bias[i];\n"
857 for (
int i = 0; i < noOfComponents; ++i)
868 " return texture2D(" +
869 opacityTableMap[i] +
",\n" +
" vec2(scalar[" +
vtk::to_string(i) +
"], " + secondAxis +
874 else if (noOfComponents == 2 && !independentComponents)
876 std::string secondAxis(useGradient ?
"grad.w" :
"yscalar.y");
878 functionBody +=
" return texture2D(" + opacityTableMap[0] +
881 secondAxis +
"));\n";
889 functionBody +=
" return texture2D(" + opacityTableMap[0] +
891 " vec2(scalar.a, grad.w));\n";
897 " vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
898 " yscalar.r = yscalar.r * in_transfer2DYAxis_scale.r + in_transfer2DYAxis_bias.r;\n"
899 " yscalar = vec4(yscalar.r);\n"
900 " return texture2D(" +
903 " vec2(scalar.a, yscalar.w));\n";
907 resStr = functionSignature +
"{\n" + functionBody +
"}\n";
915 int independentComponents,
int useGradYAxis,
std::string position,
bool requestColor =
false)
921 if (inputs.size() > 1)
924 const bool hasGradOp = ::HasGradientOpacity(inputs);
925 resStr +=
" opacity = computeOpacity(vec4(scalar), opacityTF);\n";
930 resStr +=
std::string(
" gradient = computeGradient(") + position +
", c, volume, index);\n";
931 resStr +=
" opacity *= computeGradientOpacity(gradient, gradTF);\n";
937 vtkGenericWarningMacro(<<
"ComputeOpacityEvaluationCall was called with requestColor, but "
938 "MultiVolume does not support this option yet.");
951 bool indpComps = (noOfComponents > 1 && independentComponents);
961 resStr +=
std::string(
" opacity = computeOpacity(vec4(scalar)") + compArgument +
964 if (hasGradOp || useLabelGradientOpacity)
966 resStr +=
std::string(
" gradient = computeGradient(") + position +
968 " if(gradient.w >= 0.0) {\n") +
969 (hasGradOp ? (
std::string(
" opacity *= computeGradientOpacity(gradient") +
970 compArgument +
")" + compWeights +
";\n")
973 + (useLabelGradientOpacity
974 ? (std::string(
" opacity *= computeGradientOpacityForLabel(gradient, label);\n"))
977 + std::string(
" }\n");
983 " color = texture2D(" + inputs[0].RGBTablesMap[0] +
", vec2(scalar, 0.0)).xyz;\n";
992 std::string(
" gradient = computeGradient(") + position +
", c, volume, index);\n";
994 resStr +=
std::string(
" vec4 lutRes = computeRGBAWithGrad(vec4(scalar), gradient") +
997 resStr +=
" opacity = lutRes.a;\n";
1001 resStr +=
" color = lutRes.xyz;\n";
1012 int independentComponents,
int useGradYAxis)
1014 const bool hasLighting = ::HasLighting(inputs);
1015 const bool hasGradientOp = ::HasGradientOpacity(inputs);
1019 if (inputs.size() > 1)
1024 "vec4 computeDensityGradient(in vec3 texPos, in int c, in sampler3D volume, "
1025 "const in sampler2D opacityTF, const in sampler2D gradTF, in int index, float label)\n");
1030 std::string(
"vec4 computeDensityGradient(in vec3 texPos, in int c, in sampler3D volume, "
1031 "const in sampler2D opacityTF, in int index, float label)\n");
1036 functionSignature =
std::string(
"vec4 computeDensityGradient(in vec3 texPos, in int c, in "
1037 "sampler3D volume, in int index, float label)\n");
1041 if (hasLighting || hasGradientOp)
1046 static const std::array<std::pair<const char*, const char*>, 6> results_texPos = { {
1047 {
" g1.x",
"texPosPvec[0]" },
1048 {
" g1.y",
"texPosPvec[1]" },
1049 {
" g1.z",
"texPosPvec[2]" },
1050 {
" g2.x",
"texPosNvec[0]" },
1051 {
" g2.y",
"texPosNvec[1]" },
1052 {
" g2.z",
"texPosNvec[2]" },
1055 shaderStr +=
std::string(
"// c is short for component\n") + functionSignature +
1057 " // Approximate Nabla(F) derivatives with central differences.\n"
1058 " vec3 g1; // F_front\n"
1059 " vec3 g2; // F_back\n"
1060 " vec3 xvec = vec3(in_cellStep[index].x, 0.0, 0.0);\n"
1061 " vec3 yvec = vec3(0.0, in_cellStep[index].y, 0.0);\n"
1062 " vec3 zvec = vec3(0.0, 0.0, in_cellStep[index].z);\n"
1063 " vec3 texPosPvec[3];\n"
1064 " texPosPvec[0] = texPos + xvec;\n"
1065 " texPosPvec[1] = texPos + yvec;\n"
1066 " texPosPvec[2] = texPos + zvec;\n"
1067 " vec3 texPosNvec[3];\n"
1068 " texPosNvec[0] = texPos - xvec;\n"
1069 " texPosNvec[1] = texPos - yvec;\n"
1070 " texPosNvec[2] = texPos - zvec;\n"
1076 for (
auto& gradComp : results_texPos)
1080 mapper, inputs, noOfComponents, independentComponents, useGradYAxis, gradComp.second);
1081 shaderStr +=
std::string(
" scalar = texture3D(volume,") + gradComp.second +
1083 " scalar = scalar * in_volume_scale[index][c] + in_volume_bias[index][c];\n") +
1084 opacityTFcall + gradComp.first +
" = opacity;\n";
1090 std::string(
" vec4 g1ObjDataPos[3], g2ObjDataPos[3];\n"
1091 " for (int i = 0; i < 3; ++i)\n"
1093 " g1ObjDataPos[i] = clip_texToObjMat * vec4(texPosPvec[i], 1.0);\n"
1094 " if (g1ObjDataPos[i].w != 0.0)\n"
1096 " g1ObjDataPos[i] /= g1ObjDataPos[i].w;\n"
1098 " g2ObjDataPos[i] = clip_texToObjMat * vec4(texPosNvec[i], 1.0);\n"
1099 " if (g2ObjDataPos[i].w != 0.0)\n"
1101 " g2ObjDataPos[i] /= g2ObjDataPos[i].w;\n"
1105 " for (int i = 0; i < clip_numPlanes && !g_skip; i = i + 6)\n"
1107 " vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\n"
1108 " in_clippingPlanes[i + 2],\n"
1109 " in_clippingPlanes[i + 3]);\n"
1110 " vec3 planeNormal = normalize(vec3(in_clippingPlanes[i + 4],\n"
1111 " in_clippingPlanes[i + 5],\n"
1112 " in_clippingPlanes[i + 6]));\n"
1113 " for (int j = 0; j < 3; ++j)\n"
1115 " if (dot(vec3(planeOrigin - g1ObjDataPos[j].xyz), planeNormal) > 0)\n"
1117 " g1[j] = in_clippedVoxelIntensity;\n"
1119 " if (dot(vec3(planeOrigin - g2ObjDataPos[j].xyz), planeNormal) > 0)\n"
1121 " g2[j] = in_clippedVoxelIntensity;\n"
1131 std::string(
" // Central differences: (F_front - F_back) / 2h\n"
1132 " // This version of computeGradient() is only used for lighting\n"
1133 " // calculations (only direction matters), hence the difference is\n"
1134 " // not scaled by 2h and a dummy gradient mag is returned (-1.).\n"
1135 " return vec4((g1 - g2) / in_cellSpacing[index], -1.0);\n"
1141 " // Scale values the actual scalar range.\n"
1142 " float range = in_scalarsRange[4*index+c][1] - in_scalarsRange[4*index+c][0];\n"
1143 " g1 = in_scalarsRange[4*index+c][0] + range * g1;\n"
1144 " g2 = in_scalarsRange[4*index+c][0] + range * g2;\n"
1146 " // Central differences: (F_front - F_back) / 2h\n"
1149 " float avgSpacing = (in_cellSpacing[index].x +\n"
1150 " in_cellSpacing[index].y + in_cellSpacing[index].z) / 3.0;\n"
1151 " vec3 aspect = in_cellSpacing[index] * 2.0 / avgSpacing;\n"
1153 " float grad_mag = length(g2);\n"
1155 " // Handle normalizing with grad_mag == 0.0\n"
1156 " g2 = grad_mag > 0.0 ? normalize(g2) : vec3(0.0);\n"
1158 " // Since the actual range of the gradient magnitude is unknown,\n"
1159 " // assume it is in the range [0, 0.25 * dataRange].\n"
1160 " range = range != 0 ? range : 1.0;\n"
1161 " grad_mag = grad_mag / (0.25 * range);\n"
1162 " grad_mag = clamp(grad_mag, 0.0, 1.0);\n"
1164 " return vec4(g2.xyz, grad_mag);\n"
1170 shaderStr += functionSignature +
1172 " return vec4(0.0);\n"
1189 float phase_function(float cos_angle)
1198 float g_anisotropy2 = in_anisotropy * in_anisotropy;
1200 float phase_function(float cos_angle)
1202 float d = 1.0 + g_anisotropy2 - 2.0 * in_anisotropy * cos_angle;
1203 return (1.0 - g_anisotropy2) / (d * sqrt(d));
1213 vtkVolume* vol,
int noOfComponents,
int independentComponents,
int totalNumberOfLights,
1214 int numberPositionalLights,
bool defaultLighting)
1219 \nvec4 computeLighting(vec4 color, int component, float label)\
1221 \n vec4 finalColor = vec4(0.0);\n");
1224 int const shadeReqd = volProperty->
GetShade() &&
1231 if (independentComponents)
1233 shaderStr +=
"\n int lightingComponent=component;\n";
1237 shaderStr +=
"\n int lightingComponent=0;\n";
1243 if (glMapper->GetComputeNormalFromOpacity())
1247 std::string(
" vec4 shading_gradient = computeDensityGradient(g_dataPos, component, "
1248 "in_volume[0], 0, label);\n");
1254 " vec4 shading_gradient = computeGradient(g_dataPos, component, in_volume[0], 0);\n");
1262 if (!shadeReqd || glMapper->GetComputeNormalFromOpacity())
1265 std::string(
" vec4 gradient = computeGradient(g_dataPos, component, in_volume[0], 0);\n");
1270 shaderStr +=
std::string(
" vec4 gradient = shading_gradient;\n");
1276 if (defaultLighting)
1279 vec3 diffuse = vec3(0.0);
1280 vec3 specular = vec3(0.0);
1281 vec3 normal = shading_gradient.xyz;
1282 float normalLength = length(normal);
1283 if (normalLength > 0.0)
1285 normal = normalize(normal);
1289 normal = vec3(0.0, 0.0, 0.0);
1291 // XXX: normal is oriented inside the volume, so we take -g_ldir/-g_vdir
1292 float nDotL = dot(normal, -g_ldir[0]);
1293 vec3 r = normalize(2.0 * nDotL * normal + g_ldir[0]);
1294 float vDotR = dot(r, -g_vdir[0]);
1295 if (nDotL < 0.0 && in_twoSidedLighting)
1301 diffuse = nDotL * in_diffuse[lightingComponent] *
1302 in_lightDiffuseColor[0] * color.rgb;
1303 vDotR = max(vDotR, 0.0);
1304 specular = pow(vDotR, in_shininess[lightingComponent]) *
1305 in_specular[lightingComponent] *
1306 in_lightSpecularColor[0];
1308 // For the headlight, ignore the light's ambient color
1309 // for now as it is causing the old mapper tests to fail
1310 finalColor.xyz = in_ambient[lightingComponent] * color.rgb +
1315 else if (totalNumberOfLights > 0)
1318 g_fragWorldPos = g_texToView * vec4(g_dataPos, 1.0);
1319 if (g_fragWorldPos.w != 0.0)
1321 g_fragWorldPos /= g_fragWorldPos.w;
1323 vec3 viewDirection = normalize(-g_fragWorldPos.xyz);
1324 vec3 ambient = vec3(0,0,0);
1325 vec3 diffuse = vec3(0,0,0);
1326 vec3 specular = vec3(0,0,0);
1327 vec3 vertLightDirection;
1328 vec3 normal = normalize((in_textureToEye[0] * vec4(shading_gradient.xyz, 0.0)).xyz);
1332 if (numberPositionalLights > 0)
1335 for (int posNum = 0; posNum < NUMBER_POS_LIGHTS; posNum++)
1337 float attenuation = 1.0;
1338 lightDir = in_lightDirection[posNum];
1339 vertLightDirection = (g_fragWorldPos.xyz - in_lightPosition[posNum]);
1340 float distance = length(vertLightDirection);
1341 vertLightDirection = normalize(vertLightDirection);
1343 (in_lightAttenuation[posNum].x
1344 + in_lightAttenuation[posNum].y * distance
1345 + in_lightAttenuation[posNum].z * distance * distance);
1346 // per OpenGL standard cone angle is 90 or less for a spot light
1347 if (in_lightConeAngle[posNum] <= 90.0)
1349 float coneDot = dot(vertLightDirection, lightDir);
1350 // if inside the cone
1351 if (coneDot >= cos(radians(in_lightConeAngle[posNum])))
1353 attenuation = attenuation * pow(coneDot, in_lightExponent[posNum]);
1361 float nDotL = dot(normal, vertLightDirection);
1362 if (nDotL < 0.0 && in_twoSidedLighting)
1368 float df = max(0.0, attenuation * nDotL);
1369 diffuse += (df * in_lightDiffuseColor[posNum]);
1370 vec3 r = normalize(2.0 * nDotL * normal - vertLightDirection);
1371 float rDotV = dot(-viewDirection, r);
1372 if (rDotV < 0.0 && in_twoSidedLighting)
1378 float sf = attenuation * pow(rDotV, in_shininess[lightingComponent]);
1379 specular += (sf * in_lightSpecularColor[posNum]);
1382 ambient += in_lightAmbientColor[posNum];
1388 for (int dirNum = NUMBER_POS_LIGHTS; dirNum < TOTAL_NUMBER_LIGHTS; dirNum++)
1390 vertLightDirection = in_lightDirection[dirNum];
1391 float nDotL = dot(normal, vertLightDirection);
1392 if (nDotL < 0.0 && in_twoSidedLighting)
1398 float df = max(0.0, nDotL);
1399 diffuse += (df * in_lightDiffuseColor[dirNum]);
1400 vec3 r = normalize(2.0 * nDotL * normal - vertLightDirection);
1401 float rDotV = dot(-viewDirection, r);
1404 float sf = pow(rDotV, in_shininess[lightingComponent]);
1405 specular += (sf * in_lightSpecularColor[dirNum]);
1408 ambient += in_lightAmbientColor[dirNum];
1410 finalColor.xyz = in_ambient[lightingComponent] * ambient +
1411 in_diffuse[lightingComponent] * diffuse * color.rgb +
1412 in_specular[lightingComponent] * specular;
1419 shaderStr +=
std::string(
"\n finalColor = vec4(color.rgb, 0.0);");
1422 if (glMapper->GetVolumetricScatteringBlending() > 0.0 && totalNumberOfLights > 0)
1425 float vsBlend = glMapper->GetVolumetricScatteringBlending();
1427 (vsBlend < 1.0 ?
"2.0 * in_volumetricScatteringBlending * exp( - 2.0 * "
1428 "in_volumetricScatteringBlending * shading_gradient.w * color.a)"
1429 :
"2.0 * (1.0 - in_volumetricScatteringBlending) * exp( - 2.0 * "
1430 "in_volumetricScatteringBlending * shading_gradient.w * color.a) + 2.0 * "
1431 "in_volumetricScatteringBlending - 1.0") +
1438 "vec3 view_tdir = normalize((g_eyeToTexture * vec4(viewDirection, 0.0)).xyz);\n")) +
1440 vec3 secondary_contrib = vec3(0.0);
1441 vec3 tex_light = vec3(0.0);
1442 shading_gradient.w = length(shading_gradient.xyz);
1443 vec3 diffuse_light = vec3(0.0);
1444 float attenuation = 0.0;
1445 float vol_shadow = 0.0;
1449 if (defaultLighting)
1452 tex_light = (in_inverseTextureDatasetMatrix[0] * vec4(in_eyePosObjs[0], 1.0)).xyz;
1453 phase = phase_function(-1); // always angle of pi
1454 vol_shadow = volumeShadow(g_dataPos, tex_light, 1.0, component, in_volume[0], 0, label);
1455 secondary_contrib += vol_shadow * phase * color.rgb * in_diffuse[lightingComponent] * in_lightDiffuseColor[0];
1456 secondary_contrib += in_ambient[lightingComponent] * in_lightAmbientColor[0];
1461 if (numberPositionalLights > 0)
1464 float dist_light = 0.0;
1465 for(int posNum = 0; posNum < NUMBER_POS_LIGHTS; posNum++)
1467 tex_light = g_lightPositionTex[posNum];
1468 vec3 light_vert = g_fragWorldPos.xyz - in_lightPosition[posNum];
1469 dist_light = length(light_vert);
1470 float light_angle = dot(normalize(light_vert), normalize(in_lightDirection[posNum]));
1471 phase = phase_function(dot(normalize(g_dataPos - tex_light), view_tdir));
1473 (in_lightAttenuation[posNum].x
1474 + in_lightAttenuation[posNum].y * dist_light
1475 + in_lightAttenuation[posNum].z * dist_light * dist_light);
1476 attenuation *= max(0.0, sign(light_angle - cos(radians(in_lightConeAngle[posNum]))))
1477 * pow(light_angle, in_lightExponent[posNum]);
1478 vol_shadow = volumeShadow(g_dataPos, tex_light, 1.0, component, in_volume[0], 0, label);
1479 secondary_contrib += vol_shadow * phase * attenuation * color.rgb * in_diffuse[lightingComponent] * in_lightDiffuseColor[posNum];
1480 secondary_contrib += in_ambient[lightingComponent] * in_lightAmbientColor[posNum];
1486 for(int dirNum = NUMBER_POS_LIGHTS; dirNum < TOTAL_NUMBER_LIGHTS; dirNum++)
1488 tex_light = g_lightDirectionTex[dirNum];
1489 phase = phase_function(dot(normalize(-tex_light), view_tdir));
1490 vol_shadow = volumeShadow(g_dataPos, tex_light, 0.0, component, in_volume[0], 0, label);
1491 secondary_contrib += vol_shadow * phase * color.rgb * in_diffuse[lightingComponent] * in_lightDiffuseColor[dirNum];
1492 secondary_contrib += in_ambient[lightingComponent] * in_lightAmbientColor[dirNum];
1497 shaderStr += blendingFormula +
1499 finalColor.xyz = (1.0 - vol_coef) * finalColor.xyz + vol_coef * secondary_contrib;
1509 if (noOfComponents == 1 || !independentComponents)
1514 \n if (gradient.w >= 0.0 && label == 0.0)\
1516 \n color.a *= computeGradientOpacity(gradient);\
1522 \n if (gradient.w >= 0.0 && label > 0.0)\
1524 \n color.a *= computeGradientOpacityForLabel(gradient, label);\
1528 else if (noOfComponents > 1 && independentComponents && volProperty->
HasGradientOpacity())
1531 \n if (gradient.w >= 0.0)\
1533 \n for (int i = 0; i < in_noOfComponents; ++i)\
1535 \n color.a = color.a *\
1536 \n computeGradientOpacity(gradient, i) * in_componentWeight[i];\
1543 \n finalColor.a = color.a;\
1544 \n //VTK::ComputeLighting::Exit\
1545 \n return finalColor;\
1554 int vtkNotUsed(totalNumberOfLights),
bool defaultLighting)
1564 \nvec4 computeLighting(vec3 texPos, vec4 color, const in sampler2D gradientTF, const in sampler3D volume, const in sampler2D opacityTF, const int volIdx, int component)\
1566 \n vec4 finalColor = vec4(0.0);\n");
1571 \nvec4 computeLighting(vec3 texPos, vec4 color, const in sampler3D volume, const in sampler2D opacityTF, const int volIdx, int component)\
1573 \n vec4 finalColor = vec4(0.0);\n");
1576 if (independentComponents)
1578 shaderStr +=
"\n int lightingComponent=component;\n";
1582 shaderStr +=
"\n int lightingComponent=0;\n";
1586 int const shadeReqd = volProperty->
GetShade() &&
1600 if (glMapper->GetComputeNormalFromOpacity())
1604 shaderStr +=
" vec4 shading_gradient = computeDensityGradient(texPos, component, volume, "
1605 "opacityTF, gradientTF, volIdx, 0.0);\n";
1609 shaderStr +=
" vec4 shading_gradient = computeDensityGradient(texPos, component, volume, "
1610 "opacityTF, volIdx, 0.0);\n";
1616 " vec4 shading_gradient = computeGradient(texPos, component, volume, volIdx);\n";
1623 if (!shadeReqd || glMapper->GetComputeNormalFromOpacity())
1625 shaderStr +=
" vec4 gradient = computeGradient(texPos, component, volume, volIdx);\n";
1630 shaderStr +=
" vec4 gradient = shading_gradient;\n";
1634 if (shadeReqd && defaultLighting)
1637 \n vec3 diffuse = vec3(0.0);\
1638 \n vec3 specular = vec3(0.0);\
1639 \n vec3 normal = shading_gradient.xyz;\
1640 \n float normalLength = length(normal);\
1641 \n if (normalLength > 0.0)\
1643 \n normal = normalize(normal);\
1647 \n normal = vec3(0.0, 0.0, 0.0);\
1649 \n // normal is oriented inside the volume (because normal = gradient, oriented inside the volume)\
1650 \n // thus we have to take minus everything\
1651 \n float nDotL = dot(normal, -g_ldir[volIdx]);\
1652 \n vec3 r = normalize(2.0 * nDotL * normal + g_ldir[volIdx]);\
1653 \n float vDotR = dot(r, -g_vdir[volIdx]);\
1654 \n if (nDotL < 0.0 && in_twoSidedLighting)\
1658 \n if (nDotL > 0.0)\
1660 \n diffuse = nDotL * in_diffuse[lightingComponent] *\
1661 \n in_lightDiffuseColor[0] * color.rgb;\
1662 \n vDotR = max(vDotR, 0.0);\
1663 \n specular = pow(vDotR, in_shininess[lightingComponent]) *\
1664 \n in_specular[lightingComponent] *\
1665 \n in_lightSpecularColor[0];\
1667 \n // For the headlight, ignore the light's ambient color\
1668 \n // for now as it is causing the old mapper tests to fail\
1669 \n finalColor.xyz = in_ambient[lightingComponent] * color.rgb +\
1670 \n diffuse + specular;\
1675 shaderStr +=
std::string(
"\n finalColor = vec4(color.rgb, 0.0);");
1682 if (volProperty->
HasGradientOpacity() && (noOfComponents == 1 || !independentComponents))
1685 \n if (gradient.w >= 0.0)\
1687 \n color.a = color.a *\
1688 \n computeGradientOpacity(gradient, gradientTF);\
1694 \n finalColor.a = color.a;\
1695 \n //VTK::ComputeLighting::Exit\
1696 \n return clamp(finalColor, 0.0, 1.0);\
1709 \nvec3 computeRayDirection()\
1711 \n return normalize(ip_vertexPos.xyz - in_eyePosObjs[0].xyz);\
1717 \nuniform vec3 in_projectionDirection;\
1718 \nvec3 computeRayDirection()\
1720 \n return normalize((in_inverseVolumeMatrix[0] *\
1721 \n vec4(in_projectionDirection, 0.0)).xyz);\
1731 if (inputs.size() > 1)
1734 for (
auto& item : inputs)
1736 const auto& prop = item.second.Volume->GetProperty();
1740 auto& map = item.second.RGBTablesMap;
1741 const auto numComp = map.size();
1743 "uniform sampler2D " + ArrayBaseName(map[0]) +
"[" +
vtk::to_string(numComp) +
"];\n";
1751 resStr +=
"uniform sampler2D " + ArrayBaseName(inputs[0].RGBTablesMap[0]) +
"[" +
1762 int independentComponents, std::map<int, std::string> colorTableMap)
1764 std::ostringstream ss;
1767 if (noOfComponents == 1)
1770 \nvec4 computeColor(vec4 scalar, float opacity)\
1772 \n return clamp(computeLighting(vec4(texture2D(" +
1773 colorTableMap[0] +
",\
1774 \n vec2(scalar.w, 0.0)).xyz, opacity), 0, 0.0), 0.0, 1.0);\
1778 else if (noOfComponents > 1 && independentComponents)
1780 std::ostringstream toString;
1783 \nvec4 computeColor(vec4 scalar, float opacity, int component)\
1786 for (
int i = 0; i < noOfComponents; ++i)
1790 \n if (component == " +
1791 toString.str() +
")");
1795 \n return clamp(computeLighting(vec4(texture2D(\
1800 toString.str() +
"],0.0)).xyz,\
1802 toString.str() +
", 0.0), 0.0, 1.0);\
1813 else if (noOfComponents == 2 && !independentComponents)
1816 \nvec4 computeColor(vec4 scalar, float opacity)\
1818 \n return clamp(computeLighting(vec4(texture2D(" +
1819 colorTableMap[0] +
",\
1820 \n vec2(scalar.x, 0.0)).xyz,\
1821 \n opacity), 0, 0.0), 0.0, 1.0);\
1825 else if (noOfComponents == 4 && !independentComponents)
1828 \nvec4 computeColor(vec4 scalar, float opacity)\
1830 \n return clamp(computeLighting(vec4(scalar.xyz, opacity), 3, 0.0), 0.0, 1.0);\
1837 \nvec4 computeColor(vec4 scalar, float opacity)\
1839 \n return clamp(computeLighting(vec4(scalar.xyz, opacity), 0, 0.0), 0.0, 1.0);\
1849 std::ostringstream ss;
1851 std::map<int, std::string> lastColorTableMap;
1852 for (
auto& item : inputs)
1854 auto prop = item.second.Volume->GetProperty();
1857 auto& map = item.second.RGBTablesMap;
1858 lastComponentMode = item.second.ComponentMode;
1859 lastColorTableMap = map;
1864 ss <<
"vec4 computeColor(vec4 scalar, const in sampler2D colorTF)\
1866 \n return clamp(computeLighting(vec4(texture2D(colorTF,\
1867 \n vec2(scalar.w, 0.0)).xyz, opacity), 0), 0.0, 1.0);\
1872 std::ostringstream colorDec;
1873 colorDec <<
" vec3 color = ";
1877 colorDec <<
"scalar.xyz;\n";
1884 colorDec <<
"texture2D(colorTF, vec2(scalar.w, 0.0)).xyz;\n";
1890 <<
"vec4 computeColor(vec3 texPos, vec4 scalar, float opacity, const in sampler2D colorTF, "
1891 "const in sampler2D gradientTF, const in sampler3D volume, const in sampler2D "
1892 "opacityTF, const int volIdx)\n\n"
1894 ss << colorDec.str()
1895 <<
" return clamp(computeLighting(texPos, vec4(color, opacity), gradientTF, volume, "
1897 "volIdx, 0), 0.0, 1.0);\n"
1903 <<
"vec4 computeColor(vec3 texPos, vec4 scalar, float opacity, const in sampler2D colorTF, "
1904 "const in sampler3D volume, const in sampler2D opacityTF, const int volIdx)\n\n"
1906 ss << colorDec.str()
1907 <<
" return clamp(computeLighting(texPos, vec4(color, opacity), volume, opacityTF,"
1908 "volIdx, 0), 0.0, 1.0);\n"
1920 std::ostringstream ss;
1921 for (
auto& item : inputs)
1923 auto prop = item.second.Volume->GetProperty();
1927 auto& map = item.second.OpacityTablesMap;
1928 const auto numComp = map.size();
1929 ss <<
"uniform sampler2D " << ArrayBaseName(map[0]) <<
"[" << numComp <<
"];\n";
1932 ss <<
"float computeOpacity(vec4 scalar, const in sampler2D opacityTF)\n"
1934 " return texture2D(opacityTF, vec2(scalar.w, 0)).r;\n"
1943 std::ostringstream ss;
1945 for (
auto& item : inputs)
1947 auto prop = item.second.Volume->GetProperty();
1951 auto& map = item.second.GradientOpacityTablesMap;
1952 const auto numComp = map.size();
1953 ss <<
"uniform sampler2D " << ArrayBaseName(map[0]) <<
"[" << numComp <<
"];\n";
1956 ss <<
"float computeGradientOpacity(vec4 grad, const in sampler2D gradientTF)\n"
1958 " return texture2D(gradientTF, vec2(grad.w, 0.0)).r;\n"
1966 int independentComponents, std::map<int, std::string> opacityTableMap)
1968 std::ostringstream ss;
1969 ss <<
"uniform sampler2D " << ArrayBaseName(opacityTableMap[0]) <<
"[" << noOfComponents
1973 if (noOfComponents > 1 && independentComponents)
1976 \nfloat computeOpacity(vec4 scalar, int component)\
1979 for (
int i = 0; i < noOfComponents; ++i)
1981 std::ostringstream toString;
1984 \n if (component == " +
1985 toString.str() +
")");
1989 \n return texture2D(" +
1990 opacityTableMap[i]);
1992 shaderStr +=
std::string(
",vec2(scalar[" + toString.str() +
"], 0)).r;\
1999 else if (noOfComponents == 2 && !independentComponents)
2002 \nfloat computeOpacity(vec4 scalar)\
2004 \n return texture2D(" +
2005 opacityTableMap[0] +
", vec2(scalar.y, 0)).r;\
2012 \nfloat computeOpacity(vec4 scalar)\
2014 \n return texture2D(" +
2015 opacityTableMap[0] +
", vec2(scalar.w, 0)).r;\
2023 int vtkNotUsed(independentComponents), std::map<int, std::string> colorTableMap)
2025 if (noOfComponents == 1)
2029 "vec4 computeColor(vec4 scalar, float opacity)\n"
2031 " vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
2032 " yscalar.r = yscalar.r * in_transfer2DYAxis_scale.r + in_transfer2DYAxis_bias.r;\n"
2033 " yscalar = vec4(yscalar.r);\n"
2034 " vec4 color = texture2D(" +
2037 " vec2(scalar.w, yscalar.w));\n"
2038 " return computeLighting(color, 0, 0);\n"
2041 return std::string(
"vec4 computeColor(vec4 scalar, float opacity)\n"
2043 " return vec4(0, 0, 0, 0)\n"
2050 int independentComponents, std::map<int, std::string> colorTableMap,
int useGradient)
2056 if (noOfComponents == 1)
2059 return std::string(
"vec4 computeColor(vec4 scalar, float opacity)\n"
2061 " vec4 color = texture2D(" +
2064 " vec2(scalar.w, g_gradients_0[0].w));\n"
2065 " return computeLighting(color, 0, 0);\n"
2068 else if (noOfComponents > 1 && independentComponents)
2072 shaderStr +=
std::string(
"vec4 computeColor(vec4 scalar, float opacity, int component)\n"
2075 for (
int i = 0; i < noOfComponents; ++i)
2077 std::ostringstream toString;
2080 shaderStr +=
std::string(
" if (component == " + num +
2083 " vec4 color = texture2D(" +
2087 num +
"], g_gradients_0[" + num +
2089 " return computeLighting(color, " +
2098 else if (noOfComponents == 2 && !independentComponents)
2101 return std::string(
"vec4 computeColor(vec4 scalar, float opacity)\n"
2103 " vec4 color = texture2D(" +
2106 " vec2(scalar.x, g_gradients_0[0].w));\n"
2107 " return computeLighting(color, 0, 0.0);\n"
2112 return std::string(
"vec4 computeColor(vec4 scalar, float opacity)\n"
2114 " return computeLighting(vec4(scalar.xyz, opacity), 0, 0.0);\n"
2122 std::ostringstream ss;
2123 for (
auto& item : inputs)
2125 auto prop = item.second.Volume->GetProperty();
2129 auto& map = item.second.TransferFunctions2DMap;
2130 const auto numComp = map.size();
2131 ss <<
"uniform sampler2D " << ArrayBaseName(map[0]) <<
"[" << numComp <<
"];\n";
2135 std::string(
"uniform sampler3D in_transfer2DYAxis;\n"
2136 "uniform vec4 in_transfer2DYAxis_scale;\n"
2137 "uniform vec4 in_transfer2DYAxis_bias;\n");
2145 int independentComponents, std::map<int, std::string> opacityTableMap,
int useGradient)
2147 std::ostringstream toString;
2148 if (noOfComponents > 1 && independentComponents)
2151 toString <<
"float computeOpacity(vec4 scalar, int component)\n"
2156 <<
"vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
2157 "for (int i = 0; i < 4; ++i)\n"
2159 " yscalar[i] = yscalar[i] * in_transfer2DYAxis_scale[i] + in_transfer2DYAxis_bias[i];\n"
2161 if (noOfComponents == 1)
2163 toString <<
"yscalar = vec4(yscalar.r);\n";
2167 for (
int i = 0; i < noOfComponents; ++i)
2171 toString <<
" if (component == " << i
2174 " return texture2D("
2175 << opacityTableMap[i]
2178 << i <<
"], g_gradients_0[" << i
2184 toString <<
" if (component == " << i
2187 " return texture2D("
2188 << opacityTableMap[i]
2191 << i <<
"], yscalar[" << i
2200 else if (noOfComponents == 2 && !independentComponents)
2205 toString <<
"float computeOpacity(vec4 scalar)\n"
2207 " return texture2D(" +
2208 opacityTableMap[0] +
2210 " vec2(scalar.y, g_gradients_0[0].w)).a;\n"
2216 toString <<
"float computeOpacity(vec4 scalar)\n"
2218 " return texture2D(" +
2219 opacityTableMap[0] +
2221 " vec2(scalar.y, yscalar.y)).a;\n"
2231 toString <<
"float computeOpacity(vec4 scalar)\n"
2233 " return texture2D(" +
2234 opacityTableMap[0] +
2236 " vec2(scalar.a, g_gradients_0[0].w)).a;\n"
2243 <<
"float computeOpacity(vec4 scalar)\n"
2245 " vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
2246 " yscalar.r = yscalar.r * in_transfer2DYAxis_scale.r + in_transfer2DYAxis_bias.r;\n"
2247 " yscalar = vec4(yscalar.r);\n"
2248 " return texture2D(" +
2249 opacityTableMap[0] +
2251 " vec2(scalar.a, yscalar.w)).a;\n"
2255 return toString.str();
2260 vtkVolume* vtkNotUsed(vol),
int noOfComponents,
int independentComponents,
2269 const size_t numInputs = inputs.size();
2270 const bool hasGradOp = ::HasGradientOpacity(inputs);
2275 functionSignature =
"float volumeShadow(vec3 sample_position, vec3 light_pos_dir, float is_Pos, "
2276 " in int c, in sampler3D volume, " +
2278 (numInputs > 1 && hasGradOp ? std::string(
"in sampler2D gradTF, ") :
std::string()) +
2279 "int index, float label)\n";
2284 vec3 direction = vec3(0.0);
2285 vec3 norm_dir = vec3(0.0);
2286 float maxdist = 0.0;
2289 float opacity = 0.0;
2293 float sampled_dist = 0.0;
2294 vec3 sampled_point = vec3(0.0);
2299 // direction is light_pos_dir when light is directional
2300 // and light_pos_dir - sample_position when positional
2301 direction = light_pos_dir - is_Pos * sample_position;
2302 norm_dir = normalize(direction);
2303 // introduce little offset to avoid sampling shadows at the exact
2305 sample_position += g_lengthStep * norm_dir;
2306 direction = light_pos_dir - is_Pos * sample_position;
2307 ray.origin = sample_position;
2310 ray.invDir = 1.0/ray.dir;
2311 if(!BBoxIntersect(vec3(0.0), vec3(1.0), ray, hit))
2313 // it can happen around the bounding box
2316 if(hit.tmax < g_lengthStep)
2318 // if we're too close to the bounding box
2321 // in case of directional light, we want direction not to be normalized but to go
2322 // all the way to the bbox
2323 direction *= pow(hit.tmax / length(direction), 1.0 - is_Pos);
2324 maxdist = min(hit.tmax, length(direction));
2325 maxdist = min(in_giReach, maxdist);
2326 if(maxdist < EPSILON) return 1.0;
2332 opacityEval +=
" scalar = texture3D(volume, sampled_point)[c];\n"
2333 " scalar = scalar * in_volume_scale[index][c] + in_volume_bias[index][c];\n";
2335 mapper, inputs, noOfComponents, independentComponents, useGradYAxis,
"sampled_point",
true);
2337 resStr += functionSignature +
"{\n" + declarations + rayInit +
2339 float current_dist = 0.0;
2340 float current_step = g_lengthStep;
2341 float clamped_step = 0.0;
2342 while(current_dist < maxdist)
2344 clamped_step = min(maxdist - current_dist, current_step);
2345 sampled_dist = current_dist + clamped_step * g_jitterValue;
2346 sampled_point = sample_position + sampled_dist * norm_dir;
2350 shadow *= 1.0 - opacity;
2351 current_dist += current_step;
2374 \n bool l_firstValue;\
2375 \n vec4 l_maxValue;");
2380 \n bool l_firstValue;\
2381 \n vec4 l_minValue;");
2386 \n uvec4 l_numSamples;\
2387 \n vec4 l_avgValue;");
2392 \n vec4 l_sumValue;");
2397 \n int l_initialIndex = 0;\
2398 \n float l_normValues[NUMBER_OF_CONTOURS + 2];");
2413 \n // We get data between 0.0 - 1.0 range\
2414 \n l_firstValue = true;\
2415 \n l_maxValue = vec4(0.0);");
2420 \n //We get data between 0.0 - 1.0 range\
2421 \n l_firstValue = true;\
2422 \n l_minValue = vec4(1.0);");
2427 \n //We get data between 0.0 - 1.0 range\
2428 \n l_avgValue = vec4(0.0);\
2429 \n // Keep track of number of samples\
2430 \n l_numSamples = uvec4(0);");
2435 \n //We get data between 0.0 - 1.0 range\
2436 \n l_sumValue = vec4(0.0);");
2441 \n#if NUMBER_OF_CONTOURS\
2442 \n l_normValues[0] = -1e20; //-infinity\
2443 \n l_normValues[NUMBER_OF_CONTOURS+1] = +1e20; //+infinity\
2444 \n for (int i = 0; i < NUMBER_OF_CONTOURS; i++)\
2446 \n l_normValues[i+1] = (in_isosurfacesValues[i] - in_scalarsRange[0].x) / \
2447 \n (in_scalarsRange[0].y - in_scalarsRange[0].x);\
2462 const int numInputs =
static_cast<int>(inputs.size());
2463 const int comp = numInputs == 1 ?
2466 (!independentComponents ? 1 : numInputs)
2471 std::ostringstream toShader;
2472 for (
const auto& item : inputs)
2474 auto& input = item.second;
2475 if (input.Volume->GetProperty()->HasGradientOpacity())
2477 toShader <<
"vec4 " << input.GradientCacheName <<
"[" << comp <<
"];\n";
2481 return toShader.str();
2486 int noOfComponents = 1,
int independentComponents = 0)
2488 std::ostringstream shader;
2489 if (independentComponents)
2491 if (noOfComponents == 1)
2493 shader <<
"g_gradients_0[0] = computeGradient(g_dataPos, 0, in_volume[0], 0);\n";
2498 shader <<
"for (int comp = 0; comp < in_noOfComponents; comp++)\n"
2500 " g_gradients_0[comp] = computeGradient(g_dataPos, comp, in_volume[0], 0);\n"
2506 shader <<
"g_gradients_0[0] = computeGradient(g_dataPos, 0, in_volume[0], 0);\n";
2509 return shader.str();
2516 std::ostringstream toShaderStr;
2517 toShaderStr <<
" if (!g_skip)\n"
2527 for (
auto& item : inputs)
2529 auto& input = item.second;
2530 auto property = input.Volume->GetProperty();
2532 const auto idx = i + 1;
2537 " texPos = (in_cellToPoint[" << idx <<
"] * in_inverseTextureDatasetMatrix[" << idx
2538 <<
"] * in_inverseVolumeMatrix[" << idx
2540 " in_volumeMatrix[0] * in_textureDatasetMatrix[0] * "
2541 "vec4(g_dataPos.xyz, 1.0)).xyz;\n"
2542 " if ((all(lessThanEqual(texPos, vec3(1.0))) &&\n"
2543 " all(greaterThanEqual(texPos, vec3(0.0)))))\n"
2545 " vec4 scalar = texture3D(in_volume["
2548 " scalar = scalar * in_volume_scale["
2549 << i <<
"] + in_volume_bias[" << i <<
"];\n";
2552 if (property->GetIndependentComponents())
2554 toShaderStr <<
" scalar = vec4(scalar.r);\n";
2557 toShaderStr <<
" g_srcColor = vec4(0.0);\n";
2561 std::string gradientopacity_param = (
property->HasGradientOpacity())
2562 ? input.GradientOpacityTablesMap[0] +
std::string(
", ")
2565 toShaderStr <<
" g_srcColor.a = computeOpacity(scalar,"
2566 << input.OpacityTablesMap[0]
2568 " if (g_srcColor.a > 0.0)\n"
2570 " g_srcColor = computeColor(texPos, scalar, g_srcColor.a, "
2571 << input.RGBTablesMap[0] <<
", " << gradientopacity_param <<
"in_volume[" << i
2572 <<
"], " << input.OpacityTablesMap[0] <<
", " << i <<
");\n";
2574 if (property->HasGradientOpacity())
2576 const auto& grad = input.GradientCacheName;
2577 toShaderStr <<
" " << grad <<
"[0] = computeGradient(texPos, 0, "
2578 <<
"in_volume[" << i <<
"], " << i
2582 <<
"[0].w >= 0.0)\n"
2584 " g_srcColor.a *= computeGradientOpacity("
2585 << grad <<
"[0], " << input.GradientOpacityTablesMap[0]
2592 const auto& grad = input.GradientCacheName;
2595 " " << grad <<
"[0] = computeGradient(texPos, 0, "
2596 <<
"in_volume[" << i <<
"], " << i
2598 " g_srcColor = texture2D("
2599 << input.TransferFunctions2DMap[0] <<
", vec2(scalar.r, "
2600 << input.GradientCacheName
2602 " if (g_srcColor.a > 0.0)\n"
2607 <<
" g_srcColor.rgb *= g_srcColor.a;\n"
2608 " g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;\n"
2617 toShaderStr <<
" }\n";
2619 return toShaderStr.str();
2625 int noOfComponents,
int independentComponents = 0)
2639 \n // Compute IJK vertex position for current sample in the rectilinear grid\
2640 \n vec4 dataPosWorld = in_volumeMatrix[0] * in_textureDatasetMatrix[0] * vec4(g_dataPos, 1.0);\
2641 \n dataPosWorld = dataPosWorld / dataPosWorld.w;\
2642 \n dataPosWorld.w = 1.0;\
2643 \n ivec3 ijk = ivec3(0);\
2644 \n vec3 ijkTexCoord = vec3(0.0);\
2645 \n vec3 pCoords = vec3(0.0);\
2646 \n vec3 xPrev, xNext, tmp;\
2647 \n int sz = textureSize(in_coordTexs, 0);\
2648 \n vec4 dataPosWorldScaled = dataPosWorld * vec4(in_coordsScale, 1.0) +\
2649 \n vec4(in_coordsBias, 1.0);\
2650 \n for (int j = 0; j < 3; ++j)\
2652 \n xPrev = texture1D(in_coordTexs, 0.0).xyz;\
2653 \n xNext = texture1D(in_coordTexs, (in_coordTexSizes[j] - 1) / sz).xyz;\
2654 \n if (xNext[j] < xPrev[j])\
2660 \n for (int i = 0; i < int(in_coordTexSizes[j]); i++)\
2662 \n xNext = texture1D(in_coordTexs, (i + 0.5) / sz).xyz;\
2663 \n if (dataPosWorldScaled[j] >= xPrev[j] && dataPosWorldScaled[j] < xNext[j])\
2666 \n pCoords[j] = (dataPosWorldScaled[j] - xPrev[j]) / (xNext[j] - xPrev[j]);\
2669 \n else if (dataPosWorldScaled[j] == xNext[j])\
2672 \n pCoords[j] = 1.0;\
2677 \n ijkTexCoord[j] = (ijk[j] + pCoords[j]) / in_coordTexSizes[j];\
2679 \n scalar = texture3D(in_volume[0], sign(in_cellSpacing[0]) * ijkTexCoord);\
2685 \n scalar = texture3D(in_volume[0], g_dataPos);\
2690 if (noOfComponents == 1)
2693 \n scalar.r = scalar.r * in_volume_scale[0].r + in_volume_bias[0].r;\
2694 \n scalar = vec4(scalar.r);");
2700 \n scalar = scalar * in_volume_scale[0] + in_volume_bias[0];");
2705 if (noOfComponents > 1)
2707 if (!independentComponents)
2710 \n if (l_maxValue.w < scalar.w || l_firstValue)\
2712 \n l_maxValue = scalar;\
2715 \n if (l_firstValue)\
2717 \n l_firstValue = false;\
2723 \n for (int i = 0; i < in_noOfComponents; ++i)\
2725 \n if (l_maxValue[i] < scalar[i] || l_firstValue)\
2727 \n l_maxValue[i] = scalar[i];\
2730 \n if (l_firstValue)\
2732 \n l_firstValue = false;\
2739 \n if (l_maxValue.w < scalar.x || l_firstValue)\
2741 \n l_maxValue.w = scalar.x;\
2744 \n if (l_firstValue)\
2746 \n l_firstValue = false;\
2752 if (noOfComponents > 1)
2754 if (!independentComponents)
2757 \n if (l_minValue.w > scalar.w || l_firstValue)\
2759 \n l_minValue = scalar;\
2762 \n if (l_firstValue)\
2764 \n l_firstValue = false;\
2770 \n for (int i = 0; i < in_noOfComponents; ++i)\
2772 \n if (l_minValue[i] < scalar[i] || l_firstValue)\
2774 \n l_minValue[i] = scalar[i];\
2777 \n if (l_firstValue)\
2779 \n l_firstValue = false;\
2786 \n if (l_minValue.w > scalar.x || l_firstValue)\
2788 \n l_minValue.w = scalar.x;\
2791 \n if (l_firstValue)\
2793 \n l_firstValue = false;\
2799 if (noOfComponents > 1 && independentComponents)
2802 \n for (int i = 0; i < in_noOfComponents; ++i)\
2804 \n // Get the intensity in volume scalar range\
2805 \n float intensity = in_scalarsRange[i][0] +\
2806 \n (in_scalarsRange[i][1] -\
2807 \n in_scalarsRange[i][0]) * scalar[i];\
2808 \n if (in_averageIPRange.x <= intensity &&\
2809 \n intensity <= in_averageIPRange.y)\
2811 \n l_avgValue[i] += computeOpacity(scalar, i) * scalar[i];\
2812 \n ++l_numSamples[i];\
2819 \n // Get the intensity in volume scalar range\
2820 \n float intensity = in_scalarsRange[0][0] +\
2821 \n (in_scalarsRange[0][1] -\
2822 \n in_scalarsRange[0][0]) * scalar.x;\
2823 \n if (in_averageIPRange.x <= intensity &&\
2824 \n intensity <= in_averageIPRange.y)\
2826 \n l_avgValue.x += computeOpacity(scalar) * scalar.x;\
2827 \n ++l_numSamples.x;\
2833 if (noOfComponents > 1 && independentComponents)
2836 \n for (int i = 0; i < in_noOfComponents; ++i)\
2838 \n float opacity = computeOpacity(scalar, i);\
2839 \n l_sumValue[i] = l_sumValue[i] + opacity * scalar[i];\
2845 \n float opacity = computeOpacity(scalar);\
2846 \n l_sumValue.x = l_sumValue.x + opacity * scalar.x;");
2852 \n#if NUMBER_OF_CONTOURS\
2853 \n int maxComp = 0;");
2856 if (noOfComponents > 1 && independentComponents)
2859 \n for (int i = 1; i < in_noOfComponents; ++i)\
2861 \n if (in_componentWeight[i] > in_componentWeight[maxComp])\
2864 compParamStr =
", maxComp";
2867 \n if (g_currentT == 0)\
2869 \n l_initialIndex = findIsoSurfaceIndex(scalar[maxComp], l_normValues);\
2874 \n bool shade = false;\
2875 \n l_initialIndex = clamp(l_initialIndex, 0, NUMBER_OF_CONTOURS);\
2876 \n if (scalar[maxComp] < l_normValues[l_initialIndex])\
2878 \n s = l_normValues[l_initialIndex];\
2879 \n l_initialIndex--;\
2882 \n if (scalar[maxComp] > l_normValues[l_initialIndex+1])\
2884 \n s = l_normValues[l_initialIndex+1];\
2885 \n l_initialIndex++;\
2888 \n if (shade == true)\
2890 \n vec4 vs = vec4(s);\
2891 \n g_srcColor.a = computeOpacity(vs " +
2893 \n g_srcColor = computeColor(vs, g_srcColor.a " +
2895 \n g_srcColor.rgb *= g_srcColor.a;\
2896 \n g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;\
2904 \n // test if the intersection is inside the volume bounds\
2905 \n if (any(greaterThan(g_dataPos, vec3(1.0))) || any(lessThan(g_dataPos, vec3(0.0))))\
2909 \n float opacity = computeOpacity(scalar);\
2910 \n g_fragColor = computeColor(scalar, opacity);\
2911 \n g_fragColor.rgb *= opacity;\
2912 \n g_exit = true;");
2916 if (noOfComponents > 1 && independentComponents)
2919 \n vec4 color[4]; vec4 tmp = vec4(0.0);\
2920 \n float totalAlpha = 0.0;\
2921 \n for (int i = 0; i < in_noOfComponents; ++i)\
2924 if (glMapper->GetUseDepthPass() &&
2928 \n // Data fetching from the red channel of volume texture\
2929 \n float opacity = computeOpacity(scalar, i);\
2930 \n if (opacity > 0.0)\
2932 \n g_srcColor.a = opacity;\
2939 \n // Data fetching from the red channel of volume texture\
2940 \n color[i][3] = computeOpacity(scalar, i);\
2941 \n color[i] = computeColor(scalar, color[i][3], i);\
2942 \n totalAlpha += color[i][3] * in_componentWeight[i];\
2944 \n if (totalAlpha > 0.0)\
2946 \n for (int i = 0; i < in_noOfComponents; ++i)\
2948 \n // Only let visible components contribute to the final color\
2949 \n if (in_componentWeight[i] <= 0) continue;\
2951 \n tmp.x += color[i].x * color[i].w * in_componentWeight[i];\
2952 \n tmp.y += color[i].y * color[i].w * in_componentWeight[i];\
2953 \n tmp.z += color[i].z * color[i].w * in_componentWeight[i];\
2954 \n tmp.w += ((color[i].w * color[i].w)/totalAlpha);\
2957 \n g_fragColor = (1.0f - g_fragColor.a) * tmp + g_fragColor;");
2960 else if (glMapper->GetUseDepthPass() &&
2964 \n g_srcColor = vec4(0.0);\
2965 \n g_srcColor.a = computeOpacity(scalar);");
2972 \n g_srcColor = vec4(0.0);\
2973 \n g_srcColor.a = computeOpacity(scalar);\
2974 \n if (g_srcColor.a > 0.0)\
2976 \n g_srcColor = computeColor(scalar, g_srcColor.a);");
2980 \n // Opacity calculation using compositing:\
2981 \n // Here we use front to back compositing scheme whereby\
2982 \n // the current sample value is multiplied to the\
2983 \n // currently accumulated alpha and then this product\
2984 \n // is subtracted from the sample value to get the\
2985 \n // alpha from the previous steps. Next, this alpha is\
2986 \n // multiplied with the current sample colour\
2987 \n // and accumulated to the composited colour. The alpha\
2988 \n // value from the previous steps is then accumulated\
2989 \n // to the composited colour alpha.\
2990 \n g_srcColor.rgb *= g_srcColor.a;\
2991 \n g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;");
3015 \n // Special coloring mode which renders the Prop Id in fragments that\
3016 \n // have accumulated certain level of opacity. Used during the selection\
3017 \n // pass vtkHardwareSelection::ACTOR_PASS.\
3018 \n if (g_fragColor.a > 3.0/ 255.0)\
3020 \n gl_FragData[0] = vec4(in_propId, 1.0);\
3024 \n gl_FragData[0] = vec4(0.0);\
3034 \n // Special coloring mode which renders the voxel index in fragments that\
3035 \n // have accumulated certain level of opacity. Used during the selection\
3036 \n // pass vtkHardwareSelection::ID_LOW24.\
3037 \n if (g_fragColor.a > 3.0/ 255.0)\
3039 \n uvec3 volumeDim = uvec3(in_textureExtentsMax - in_textureExtentsMin);\
3040 \n uvec3 voxelCoords = uvec3(vec3(volumeDim) * g_dataPos);\
3041 \n // vtkHardwareSelector assumes index 0 to be empty space, so add uint(1).\
3042 \n uint idx = volumeDim.x * volumeDim.y * voxelCoords.z +\
3043 \n volumeDim.x * voxelCoords.y + voxelCoords.x + uint(1);\
3044 \n gl_FragData[0] = vec4(float(idx % uint(256)) / 255.0,\
3045 \n float((idx / uint(256)) % uint(256)) / 255.0,\
3046 \n float((idx / uint(65536)) % uint(256)) / 255.0, 1.0);\
3050 \n gl_FragData[0] = vec4(0.0);\
3060 \n // Special coloring mode which renders the voxel index in fragments that\
3061 \n // have accumulated certain level of opacity. Used during the selection\
3062 \n // pass vtkHardwareSelection::ID_MID24.\
3063 \n if (g_fragColor.a > 3.0/ 255.0)\
3065 \n uvec3 volumeDim = uvec3(in_textureExtentsMax - in_textureExtentsMin);\
3066 \n uvec3 voxelCoords = uvec3(vec3(volumeDim) * g_dataPos);\
3067 \n // vtkHardwareSelector assumes index 0 to be empty space, so add uint(1).\
3068 \n uint idx = volumeDim.x * volumeDim.y * voxelCoords.z +\
3069 \n volumeDim.x * voxelCoords.y + voxelCoords.x + uint(1);\
3070 \n idx = ((idx & 0xff000000u) >> 24u);\
3071 \n gl_FragData[0] = vec4(float(idx % uint(256)) / 255.0,\
3072 \n float((idx / uint(256)) % uint(256)) / 255.0,\
3073 \n float(idx / uint(65536)) / 255.0, 1.0);\
3077 \n gl_FragData[0] = vec4(0.0);\
3084 vtkVolume* vtkNotUsed(vol),
int noOfComponents,
int independentComponents = 0)
3096 if (noOfComponents > 1 && independentComponents)
3099 \n g_srcColor = vec4(0);\
3100 \n for (int i = 0; i < in_noOfComponents; ++i)\
3102 \n vec4 tmp = computeColor(l_maxValue, computeOpacity(l_maxValue, i), i);\
3103 \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
3104 \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
3105 \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
3106 \n g_srcColor[3] += tmp[3] * in_componentWeight[i];\
3108 \n g_fragColor = g_srcColor;");
3113 \n g_srcColor = computeColor(l_maxValue,\
3114 \n computeOpacity(l_maxValue));\
3115 \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
3116 \n g_fragColor.a = g_srcColor.a;");
3121 if (noOfComponents > 1 && independentComponents)
3124 \n g_srcColor = vec4(0);\
3125 \n for (int i = 0; i < in_noOfComponents; ++i)\
3127 \n vec4 tmp = computeColor(l_minValue, computeOpacity(l_minValue, i), i);\
3128 \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
3129 \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
3130 \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
3131 \n g_srcColor[2] += tmp[3] * tmp[3] * in_componentWeight[i];\
3133 \n g_fragColor = g_srcColor;");
3138 \n g_srcColor = computeColor(l_minValue,\
3139 \n computeOpacity(l_minValue));\
3140 \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
3141 \n g_fragColor.a = g_srcColor.a;");
3146 if (noOfComponents > 1 && independentComponents)
3149 \n for (int i = 0; i < in_noOfComponents; ++i)\
3151 \n if (l_numSamples[i] == uint(0))\
3155 \n l_avgValue[i] = l_avgValue[i] * in_componentWeight[i] /\
3156 \n l_numSamples[i];\
3159 \n l_avgValue[0] += l_avgValue[i];\
3162 \n l_avgValue[0] = clamp(l_avgValue[0], 0.0, 1.0);\
3163 \n g_fragColor = vec4(vec3(l_avgValue[0]), 1.0);");
3168 \n if (l_numSamples.x == uint(0))\
3174 \n l_avgValue.x /= l_numSamples.x;\
3175 \n l_avgValue.x = clamp(l_avgValue.x, 0.0, 1.0);\
3176 \n g_fragColor = vec4(vec3(l_avgValue.x), 1.0);\
3182 if (noOfComponents > 1 && independentComponents)
3186 \n l_sumValue.x *= in_componentWeight.x;\
3187 \n for (int i = 1; i < in_noOfComponents; ++i)\
3189 \n l_sumValue.x += l_sumValue[i] * in_componentWeight[i];\
3191 \n l_sumValue.x = clamp(l_sumValue.x, 0.0, 1.0);\
3192 \n g_fragColor = vec4(vec3(l_sumValue.x), 1.0);");
3197 \n l_sumValue.x = clamp(l_sumValue.x, 0.0, 1.0);\
3198 \n g_fragColor = vec4(vec3(l_sumValue.x), 1.0);");
3219 \n const float g_opacityThreshold = 1.0 - 1.0 / 255.0;");
3227 \n uniform vec3 in_propId;");
3236 \n // Flag to indicate if the raymarch loop should terminate \
3237 \n bool stop = false;\
3239 \n g_terminatePointMax = 0.0;\
3241 \n vec4 l_depthValue = texture2D(in_depthSampler, fragTexCoord);\
3243 \n if(gl_FragCoord.z >= l_depthValue.x)\
3248 \n // color buffer or max scalar buffer have a reduced size.\
3249 \n fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
3250 \n in_inverseOriginalWindowSize;\
3258 if (sliceFunc->
IsA(
"vtkPlane"))
3262 \n // Intersection with plane\
3263 \n float t = intersectRayPlane(ip_vertexPos, rayDir);\
3264 \n vec4 intersection = vec4(ip_vertexPos + t * rayDir, 1.0);\
3265 \n g_intersection = (in_inverseTextureDatasetMatrix[0] * intersection).xyz;\
3266 \n vec4 intersDC = in_projectionMatrix * in_modelViewMatrix * in_volumeMatrix[0] * intersection;\
3267 \n intersDC.xyz /= intersDC.w;\
3268 \n vec4 intersWin = NDCToWindow(intersDC.x, intersDC.y, intersDC.z);\
3269 \n if(intersWin.z >= l_depthValue.x)\
3277 vtkErrorWithObjectMacro(
3278 sliceFunc,
"Implicit function type is not supported by this mapper.");
3284 \n // Compute max number of iterations it will take before we hit\
3285 \n // the termination point\
3287 \n // Abscissa of the point on the depth buffer along the ray.\
3288 \n // point in texture coordinates\
3289 \n vec4 rayTermination = WindowToNDC(gl_FragCoord.x, gl_FragCoord.y, l_depthValue.x);\
3291 \n // From normalized device coordinates to eye coordinates.\
3292 \n // in_projectionMatrix is inversed because of way VT\
3293 \n // From eye coordinates to texture coordinates\
3294 \n rayTermination = ip_inverseTextureDataAdjusted *\
3295 \n in_inverseVolumeMatrix[0] *\
3296 \n in_inverseModelViewMatrix *\
3297 \n in_inverseProjectionMatrix *\
3299 \n g_rayTermination = rayTermination.xyz / rayTermination.w;\
3301 \n // Setup the current segment:\
3302 \n g_dataPos = g_rayOrigin;\
3303 \n g_terminatePos = g_rayTermination;\
3305 \n g_terminatePointMax = length(g_terminatePos.xyz - g_dataPos.xyz) /\
3306 \n length(g_dirStep);\
3307 \n g_currentT = 0.0;");
3317 \n if(any(greaterThan(max(g_dirStep, vec3(0.0))*(g_dataPos - in_texMax[0]),vec3(0.0))) ||\
3318 \n any(greaterThan(min(g_dirStep, vec3(0.0))*(g_dataPos - in_texMin[0]),vec3(0.0))))\
3323 \n // Early ray termination\
3324 \n // if the currently composited colour alpha is already fully saturated\
3325 \n // we terminated the loop or if we have hit an obstacle in the\
3326 \n // direction of they ray (using depth buffer) we terminate as well.\
3327 \n if((g_fragColor.a > g_opacityThreshold) || \
3328 \n g_currentT >= g_terminatePointMax)\
3359 \nuniform float in_croppingPlanes[6];\
3360 \nuniform int in_croppingFlags [32];\
3361 \nfloat croppingPlanesTexture[6];\
3363 \n// X: axis = 0, Y: axis = 1, Z: axis = 2\
3364 \n// cp Cropping plane bounds (minX, maxX, minY, maxY, minZ, maxZ)\
3365 \nint computeRegionCoord(float cp[6], vec3 pos, int axis)\
3367 \n int cpmin = axis * 2;\
3368 \n int cpmax = cpmin + 1;\
3370 \n if (pos[axis] < cp[cpmin])\
3374 \n else if (pos[axis] >= cp[cpmin] &&\
3375 \n pos[axis] < cp[cpmax])\
3379 \n else if (pos[axis] >= cp[cpmax])\
3386 \nint computeRegion(float cp[6], vec3 pos)\
3388 \n return (computeRegionCoord(cp, pos, 0) +\
3389 \n (computeRegionCoord(cp, pos, 1) - 1) * 3 +\
3390 \n (computeRegionCoord(cp, pos, 2) - 1) * 9);\
3404 \n // Convert cropping region to texture space\
3405 \n mat4 datasetToTextureMat = in_inverseTextureDatasetMatrix[0];\
3407 \n vec4 tempCrop = vec4(in_croppingPlanes[0], 0.0, 0.0, 1.0);\
3408 \n tempCrop = datasetToTextureMat * tempCrop;\
3409 \n if (tempCrop[3] != 0.0)\
3411 \n tempCrop[0] /= tempCrop[3];\
3413 \n croppingPlanesTexture[0] = tempCrop[0];\
3415 \n tempCrop = vec4(in_croppingPlanes[1], 0.0, 0.0, 1.0);\
3416 \n tempCrop = datasetToTextureMat * tempCrop;\
3417 \n if (tempCrop[3] != 0.0)\
3419 \n tempCrop[0] /= tempCrop[3];\
3421 \n croppingPlanesTexture[1] = tempCrop[0];\
3423 \n tempCrop = vec4(0.0, in_croppingPlanes[2], 0.0, 1.0);\
3424 \n tempCrop = datasetToTextureMat * tempCrop;\
3425 \n if (tempCrop[3] != 0.0)\
3427 \n tempCrop[1] /= tempCrop[3];\
3429 \n croppingPlanesTexture[2] = tempCrop[1];\
3431 \n tempCrop = vec4(0.0, in_croppingPlanes[3], 0.0, 1.0);\
3432 \n tempCrop = datasetToTextureMat * tempCrop;\
3433 \n if (tempCrop[3] != 0.0)\
3435 \n tempCrop[1] /= tempCrop[3];\
3437 \n croppingPlanesTexture[3] = tempCrop[1];\
3439 \n tempCrop = vec4(0.0, 0.0, in_croppingPlanes[4], 1.0);\
3440 \n tempCrop = datasetToTextureMat * tempCrop;\
3441 \n if (tempCrop[3] != 0.0)\
3443 \n tempCrop[2] /= tempCrop[3];\
3445 \n croppingPlanesTexture[4] = tempCrop[2];\
3447 \n tempCrop = vec4(0.0, 0.0, in_croppingPlanes[5], 1.0);\
3448 \n tempCrop = datasetToTextureMat * tempCrop;\
3449 \n if (tempCrop[3] != 0.0)\
3451 \n tempCrop[2] /= tempCrop[3];\
3453 \n croppingPlanesTexture[5] = tempCrop[2];");
3466 \n // Determine region\
3467 \n int regionNo = computeRegion(croppingPlanesTexture, g_dataPos);\
3469 \n // Do & operation with cropping flags\
3470 \n // Pass the flag that its Ok to sample or not to sample\
3471 \n if (in_croppingFlags[regionNo] == 0)\
3473 \n // Skip this voxel\
3502 \n /// We support only 8 clipping planes for now\
3503 \n /// The first value is the size of the data array for clipping\
3504 \n /// planes (origin, normal)\
3505 \n uniform float in_clippingPlanes[49];\
3506 \n uniform float in_clippedVoxelIntensity;\
3508 \n int clip_numPlanes;\
3509 \n vec3 clip_rayDirObj;\
3510 \n mat4 clip_texToObjMat;\
3511 \n mat4 clip_objToTexMat;\
3513 \n// Tighten the sample range as needed to account for clip planes. \
3514 \n// Arguments are in texture coordinates. \
3515 \n// Returns true if the range is at all valid after clipping. If not, \
3516 \n// the fragment should be discarded. \
3517 \nbool AdjustSampleRangeForClipping(inout vec3 startPosTex, inout vec3 stopPosTex) \
3519 \n vec4 startPosObj = vec4(0.0);\
3521 \n startPosObj = clip_texToObjMat * vec4(startPosTex - g_rayJitter, 1.0);\
3522 \n startPosObj = startPosObj / startPosObj.w;\
3523 \n startPosObj.w = 1.0;\
3526 \n vec4 stopPosObj = vec4(0.0);\
3528 \n stopPosObj = clip_texToObjMat * vec4(stopPosTex, 1.0);\
3529 \n stopPosObj = stopPosObj / stopPosObj.w;\
3530 \n stopPosObj.w = 1.0;\
3533 \n for (int i = 0; i < clip_numPlanes; i = i + 6)\
3535 \n vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\
3536 \n in_clippingPlanes[i + 2],\
3537 \n in_clippingPlanes[i + 3]);\
3538 \n vec3 planeNormal = normalize(vec3(in_clippingPlanes[i + 4],\
3539 \n in_clippingPlanes[i + 5],\
3540 \n in_clippingPlanes[i + 6]));\
3542 \n // Abort if the entire segment is clipped:\
3543 \n // (We can do this before adjusting the term point, since it'll \
3544 \n // only move further into the clipped area)\
3545 \n float startDistance = dot(planeNormal, planeOrigin - startPosObj.xyz);\
3546 \n float stopDistance = dot(planeNormal, planeOrigin - stopPosObj.xyz);\
3547 \n bool startClipped = startDistance > 0.0;\
3548 \n bool stopClipped = stopDistance > 0.0;\
3549 \n if (startClipped && stopClipped)\
3554 \n float rayDotNormal = dot(clip_rayDirObj, planeNormal);\
3555 \n bool frontFace = rayDotNormal > 0.0;\
3557 \n // Move the start position further from the eye if needed:\
3558 \n if (frontFace && // Observing from the clipped side (plane's front face)\
3559 \n startDistance > 0.0) // Ray-entry lies on the clipped side.\
3561 \n // Scale the point-plane distance to the ray direction and update the\
3563 \n float rayScaledDist = startDistance / rayDotNormal;\
3564 \n startPosObj = vec4(startPosObj.xyz + rayScaledDist * clip_rayDirObj, 1.0);\
3565 \n vec4 newStartPosTex = clip_objToTexMat * vec4(startPosObj.xyz, 1.0);\
3566 \n newStartPosTex /= newStartPosTex.w;\
3567 \n startPosTex = newStartPosTex.xyz;\
3568 \n startPosTex += g_rayJitter;\
3571 \n // Move the end position closer to the eye if needed:\
3572 \n if (!frontFace && // Observing from the unclipped side (plane's back face)\
3573 \n stopDistance > 0.0) // Ray-entry lies on the unclipped side.\
3575 \n // Scale the point-plane distance to the ray direction and update the\
3576 \n // termination point.\
3577 \n float rayScaledDist = stopDistance / rayDotNormal;\
3578 \n stopPosObj = vec4(stopPosObj.xyz + rayScaledDist * clip_rayDirObj, 1.0);\
3579 \n vec4 newStopPosTex = clip_objToTexMat * vec4(stopPosObj.xyz, 1.0);\
3580 \n newStopPosTex /= newStopPosTex.w;\
3581 \n stopPosTex = newStopPosTex.xyz;\
3585 \n if (any(greaterThan(startPosTex, in_texMax[0])) ||\
3586 \n any(lessThan(startPosTex, in_texMin[0])))\
3609 \n vec4 tempClip = in_volumeMatrix[0] * vec4(rayDir, 0.0);\
3610 \n if (tempClip.w != 0.0)\
3612 \n tempClip = tempClip/tempClip.w;\
3613 \n tempClip.w = 1.0;\
3615 \n clip_rayDirObj = normalize(tempClip.xyz);");
3620 clip_rayDirObj = normalize(in_projectionDirection);");
3624 \n clip_numPlanes = int(in_clippingPlanes[0]);\
3625 \n clip_texToObjMat = in_volumeMatrix[0] * inverse(ip_inverseTextureDataAdjusted);\
3626 \n clip_objToTexMat = ip_inverseTextureDataAdjusted * in_inverseVolumeMatrix[0];\
3628 \n // Adjust for clipping.\
3629 \n if (!AdjustSampleRangeForClipping(g_rayOrigin, g_rayTermination))\
3630 \n { // entire ray is clipped.\
3634 \n // Update the segment post-clip:\
3635 \n g_dataPos = g_rayOrigin;\
3636 \n g_terminatePos = g_rayTermination;\
3637 \n g_terminatePointMax = length(g_terminatePos.xyz - g_dataPos.xyz) /\
3638 \n length(g_dirStep);\
3663 if (!mask || !maskInput)
3685 \nvec4 maskValue = texture3D(in_mask, g_dataPos);\
3686 \nif(maskValue.r <= 0.0)\
3705 \nuniform float in_maskBlendFactor;\
3706 \nuniform sampler2D in_labelMapTransfer;\
3707 \nuniform float in_mask_scale;\
3708 \nuniform float in_mask_bias;\
3709 \nuniform int in_labelMapNumLabels;\
3726 \nvec4 scalar = texture3D(in_volume[0], g_dataPos);");
3729 if (noOfComponents == 1)
3732 \n scalar.r = scalar.r * in_volume_scale[0].r + in_volume_bias[0].r;\
3733 \n scalar = vec4(scalar.r);");
3739 \n scalar = scalar * in_volume_scale[0] + in_volume_bias[0];");
3746 \nif (in_maskBlendFactor == 0.0)\
3748 \n g_srcColor.a = computeOpacity(scalar);\
3749 \n if (g_srcColor.a > 0)\
3751 \n g_srcColor = computeColor(scalar, g_srcColor.a);\
3756 \n float opacity = computeOpacity(scalar);\
3757 \n // Get the mask value at this same location\
3758 \n vec4 maskValue = texture3D(in_mask, g_dataPos);\
3759 \n maskValue.r = maskValue.r * in_mask_scale + in_mask_bias;\
3760 \n // Quantize the height of the labelmap texture over number of labels\
3761 \n if (in_labelMapNumLabels > 0)\
3764 \n floor(maskValue.r * in_labelMapNumLabels) /\
3765 \n in_labelMapNumLabels;\
3769 \n maskValue.r = 0.0;\
3771 \n if(maskValue.r == 0.0)\
3773 \n g_srcColor.a = opacity;\
3774 \n if (g_srcColor.a > 0)\
3776 \n g_srcColor = computeColor(scalar, g_srcColor.a);\
3781 \n g_srcColor = texture2D(in_labelMapTransfer,\
3782 \n vec2(scalar.r, maskValue.r));\
3783 \n if (g_srcColor.a > 0)\
3785 \n g_srcColor = computeLighting(g_srcColor, 0, maskValue.r);\
3787 \n if (in_maskBlendFactor < 1.0)\
3789 \n vec4 color = opacity > 0 ? computeColor(scalar, opacity) : vec4(0);\
3790 \n g_srcColor = (1.0 - in_maskBlendFactor) * color +\
3791 \n in_maskBlendFactor * g_srcColor;\
3802 return std::string(
"uniform bool in_clampDepthToBackface;\n"
3803 "vec3 l_opaqueFragPos;\n"
3804 "bool l_updateDepth;\n");
3812 \n l_opaqueFragPos = vec3(-1.0);\
3813 \n if(in_clampDepthToBackface)\
3815 \n l_opaqueFragPos = g_dataPos;\
3817 \n l_updateDepth = true;");
3825 \n if(!g_skip && g_srcColor.a > 0.0 && l_updateDepth)\
3827 \n l_opaqueFragPos = g_dataPos;\
3828 \n l_updateDepth = false;\
3837 \n if (l_opaqueFragPos == vec3(-1.0))\
3839 \n gl_FragData[1] = vec4(1.0);\
3843 \n vec4 depthValue = in_projectionMatrix * in_modelViewMatrix *\
3844 \n in_volumeMatrix[0] * in_textureDatasetMatrix[0] *\
3845 \n vec4(l_opaqueFragPos, 1.0);\
3846 \n depthValue /= depthValue.w;\
3847 \n gl_FragData[1] = vec4(vec3(0.5 * (gl_DepthRange.far -\
3848 \n gl_DepthRange.near) * depthValue.z + 0.5 *\
3849 \n (gl_DepthRange.far + gl_DepthRange.near)), 1.0);\
3858 \n vec3 l_isoPos = g_dataPos;");
3866 \n if(!g_skip && g_srcColor.a > 0.0)\
3868 \n l_isoPos = g_dataPos;\
3869 \n g_exit = true; g_skip = true;\
3878 \n vec4 depthValue = in_projectionMatrix * in_modelViewMatrix *\
3879 \n in_volumeMatrix[0] * in_textureDatasetMatrix[0] *\
3880 \n vec4(l_isoPos, 1.0);\
3881 \n gl_FragData[0] = vec4(l_isoPos, 1.0);\
3882 \n gl_FragData[1] = vec4(vec3((depthValue.z/depthValue.w) * 0.5 + 0.5),\
3891 \n g_texToView = in_modelViewMatrix * in_volumeMatrix[0] * in_textureDatasetMatrix[0];\
3892 \n initializeRayCast();\
3893 \n castRay(-1.0, -1.0);\
3894 \n finalizeRayCast();");
3899 const std::vector<std::string>& varNames,
size_t usedNames)
3902 for (
size_t i = 0; i < usedNames; i++)
3904 shader +=
"uniform sampler2D " + varNames[i] +
";\n";
3911 const std::vector<std::string>& varNames,
size_t usedNames)
3914 for (
size_t i = 0; i < usedNames; i++)
3916 std::stringstream ss;
3918 shader +=
" gl_FragData[" + ss.str() +
"] = texture2D(" + varNames[i] +
", texCoord);\n";
3920 shader +=
" return;\n";
3923 VTK_ABI_NAMESPACE_END
3926 #endif // vtkVolumeShaderComposer_h
abstract interface for implicit functions
std::string RenderToImageDeclarationFragment(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
virtual float GetScatteringAnisotropy()
Get/Set the volume's scattering anisotropy.
std::string PreComputeGradientsImpl(vtkRenderer *ren, vtkVolume *vol, int noOfComponents=1, int independentComponents=0)
represents a volume (data & properties) in a rendered scene
std::string BinaryMaskDeclaration(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType)
std::string BaseDeclarationFragment(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int totalNumberOfLights, int numberPositionalLights, bool defaultLighting, int noOfComponents, int independentComponents)
virtual int GetUseClippedVoxelIntensity()
Set/Get whether to use a fixed intensity value for voxels in the clipped space for gradient calculati...
std::string ClippingDeclarationVertex(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string RenderToImageInit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
Abstract class for a volume mapper.
std::string DepthPassImplementation(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string BinaryMaskImplementation(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType)
std::string ComputeGradientOpacityMulti1DDecl(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string PickingActorPassDeclaration(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string CompositeMaskImplementation(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType, int noOfComponents)
std::string BaseExit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string TerminationExit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
virtual int GetBlendMode()
Set/Get the blend mode.
vtkUnsignedCharArray * GetCellGhostArray()
Get the array that defines the ghost type of each cell.
Creates and manages the volume texture rendered by vtkOpenGLGPUVolumeRayCastMapper.
std::map< int, vtkVolumeInputHelper > VolumeInputMap
std::string PickingIdHigh24PassExit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string CroppingInit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string ClippingInit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string PickingActorPassExit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
bool HasLabelGradientOpacity()
std::string ClippingImplementation(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string BaseImplementation(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
virtual vtkVolumeProperty * GetProperty()
Set/Get the volume property.
std::string PickingIdLow24PassExit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string ComputeGradientOpacity1DDecl(vtkVolume *vol, int noOfComponents, int independentComponents, std::map< int, std::string > gradientTableMap)
std::string ShadingExit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents=0)
std::string ComputeClipPositionImplementation(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string ComputeVolumetricShadowDec(vtkOpenGLGPUVolumeRayCastMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int useGradYAxis)
abstract specification for renderers
virtual vtkImplicitFunction * GetSliceFunction()
Get/Set the function used for slicing.
vtkUnsignedCharArray * GetPointGhostArray()
Gets the array that defines the ghost type of each point.
std::string ComputeOpacityEvaluationCall(vtkOpenGLGPUVolumeRayCastMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int noOfComponents, int independentComponents, int useGradYAxis, std::string position, bool requestColor=false)
std::string TerminationImplementation(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string VTKCOMMONCORE_EXPORT to_string(vtkArrayComponents enumerant)
Given an enumerant, return a human-presentable string with its value.
std::string ComputeLightingMultiDeclaration(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents, int totalNumberOfLights, bool defaultLighting)
std::string ComputeColorUniforms(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int noOfComponents, vtkVolumeProperty *volProp)
virtual vtkPlaneCollection * GetClippingPlanes()
Get/Set the vtkPlaneCollection which specifies the clipping planes.
virtual int GetTransferFunctionMode()
Color-opacity transfer function mode.
vtkCamera * GetActiveCamera()
Get the current camera.
std::string TerminationInit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string TerminationDeclarationVertex(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string ComputeRayDirectionDeclaration(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents)
std::string PhaseFunctionDeclaration(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
int GetShade(int index)
Set/Get the shading of a volume.
std::string ComputeColorDeclaration(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents, std::map< int, std::string > colorTableMap)
std::string CroppingImplementation(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
virtual vtkDataSet * GetInput()
Set/Get the input data.
OpenGL implementation of volume rendering through ray-casting.
static vtkOpenGLGPUVolumeRayCastMapper * SafeDownCast(vtkObjectBase *o)
std::string CroppingExit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
virtual int GetDisableGradientOpacity(int index)
Enable/Disable the gradient opacity function for the given component.
std::string ComputeRGBA2DWithGradientDeclaration(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents, std::map< int, std::string > opacityTableMap, int useGradient)
std::string TerminationDeclarationFragment(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string GradientCacheDec(vtkRenderer *ren, vtkVolume *vol, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int independentComponents=0)
std::string ComputeLightingDeclaration(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents, int totalNumberOfLights, int numberPositionalLights, bool defaultLighting)
static vtkRectilinearGrid * SafeDownCast(vtkObjectBase *o)
topologically and geometrically regular array of data
std::string ImageSampleImplementationFrag(const std::vector< std::string > &varNames, size_t usedNames)
bool HasGradientOpacity(int index=0)
Check whether or not we have the gradient opacity.
std::string ComputeColor2DYAxisDeclaration(int noOfComponents, int independentComponents, std::map< int, std::string > colorTableMap)
std::string ShadingSingleInput(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType, int noOfComponents, int independentComponents=0)
std::string ImageSampleDeclarationFrag(const std::vector< std::string > &varNames, size_t usedNames)
static vtkGPUVolumeRayCastMapper * SafeDownCast(vtkObjectBase *o)
std::string RenderToImageExit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
static vtkDataSet * SafeDownCast(vtkObjectBase *o)
std::string WorkerImplementation(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string ComputeOpacityDeclaration(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents, std::map< int, std::string > opacityTableMap)
std::string ComputeColor2DDeclaration(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents, std::map< int, std::string > colorTableMap, int useGradient)
virtual vtkTypeBool GetUseJittering()
If UseJittering is on, each ray traversal direction will be perturbed slightly using a noise-texture ...
represents the common properties for rendering a volume.
virtual vtkTypeBool GetCropping()
Turn On/Off orthogonal cropping.
std::string Transfer2DDeclaration(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string ComputeColorMultiDeclaration(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, bool useGradientTF)
std::string ComputeOpacityMultiDeclaration(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string ClippingDeclarationFragment(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string ShadingDeclarationFragment(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
virtual float GetVolumetricScatteringBlending()
This parameter controls the blending between surfacic approximation and volumetric multi-scattering...
std::string CroppingDeclarationFragment(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string DepthPassInit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string ComputeMatricesInit(vtkOpenGLGPUVolumeRayCastMapper *mapper, int numberPositionalLights)
virtual int GetCurrentPass()
virtual vtkTypeBool GetParallelProjection()
Set/Get the value of the ParallelProjection instance variable.
std::string ComputeOpacity2DDeclaration(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents, std::map< int, std::string > opacityTableMap, int useGradient)
virtual vtkTypeBool GetUseDepthPass()
If UseDepthPass is on, the mapper will use two passes.
std::string CroppingDeclarationVertex(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string ShadingMultipleInputs(vtkVolumeMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string ComputeTextureCoordinates(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string BaseInit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, bool defaultLighting)
virtual vtkTypeBool IsA(const char *type)
Return 1 if this class is the same type of (or a subclass of) the named class.
std::string DepthPassExit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string RenderToImageImplementation(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string ComputeGradientDeclaration(vtkOpenGLGPUVolumeRayCastMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string ShadingInit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string ComputeDensityGradientDeclaration(vtkOpenGLGPUVolumeRayCastMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int noOfComponents, int independentComponents, int useGradYAxis)
std::string BaseDeclarationVertex(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, bool multipleInputs)
std::string CompositeMaskDeclarationFragment(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol, vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType)
std::string ShadingDeclarationVertex(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)
std::string ClippingExit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vol)