16 #ifndef vtkVolumeShaderComposer_h
17 #define vtkVolumeShaderComposer_h
38 for (
auto& item : inputs)
51 for (
auto& item : inputs)
54 const bool lighting = volProp->
GetShade() == 1;
63 for (
auto& item : inputs)
67 if (useClippedVoxelIntensity)
77 const std::string base = arrayName.substr(0, arrayName.length() - 3);
95 " //Transform vertex (data coordinates) to clip coordinates\n"
96 " // p_clip = T_ProjViewModel * T_dataToWorld * p_data\n"
97 " vec4 pos = in_projectionMatrix * in_modelViewMatrix * in_volumeMatrix[0] *\n"
98 " vec4(in_vertexPos.xyz, 1.0);\n"
99 " gl_Position = pos;\n");
107 " // Transform vertex (data coordinates) to texture coordinates.\n"
108 " // p_texture = T_dataToTex * p_data\n"
109 " vec3 uvx = sign(in_cellSpacing[0]) * (in_inverseTextureDatasetMatrix[0] *\n"
110 " vec4(in_vertexPos, 1.0)).xyz;\n"
112 " // For point dataset, we offset the texture coordinate\n"
113 " // to account for OpenGL treating voxel at the center of the cell.\n"
114 " // Transform cell tex-coordinates to point tex-coordinates (cellToPoint\n"
115 " // is an identity matrix in the case of cell data).\n"
116 " ip_textureCoords = (in_cellToPoint[0] * vec4(uvx, 1.0)).xyz;\n"
117 " ip_inverseTextureDataAdjusted = in_cellToPoint[0] * in_inverseTextureDatasetMatrix[0];\n");
122 vtkVolume* vtkNotUsed(vol),
bool multipleInputs)
125 const int numInputs = gpuMapper->GetInputCount();
127 std::ostringstream ss;
128 ss <<
"uniform vec3 in_cellSpacing[" << numInputs
130 "uniform mat4 in_modelViewMatrix;\n"
131 "uniform mat4 in_projectionMatrix;\n";
133 const int numTransf = multipleInputs ? numInputs + 1 : 1;
134 ss <<
"uniform mat4 in_volumeMatrix[" << numTransf
136 "uniform mat4 in_inverseTextureDatasetMatrix["
139 "uniform mat4 in_cellToPoint["
143 "//This variable could be 'invariant varying' but it is declared\n"
144 "//as 'varying' to avoid compiler compatibility issues.\n"
145 "out mat4 ip_inverseTextureDataAdjusted;\n";
153 int numberPositionalLights,
bool defaultLighting,
int noOfComponents,
int independentComponents)
155 const int numInputs =
static_cast<int>(inputs.size());
157 std::ostringstream toShaderStr;
158 toShaderStr <<
"uniform sampler3D in_volume[" << numInputs <<
"];\n";
160 toShaderStr <<
"uniform vec4 in_volume_scale[" << numInputs
162 "uniform vec4 in_volume_bias["
163 << numInputs <<
"];\n";
167 toShaderStr <<
"uniform sampler1D in_coordTexs;\n";
168 toShaderStr <<
"uniform vec3 in_coordTexSizes;\n";
169 toShaderStr <<
"uniform vec3 in_coordsScale;\n";
170 toShaderStr <<
"uniform vec3 in_coordsBias;\n";
175 toShaderStr <<
"uniform sampler3D in_blanking;\n";
178 toShaderStr <<
"uniform int in_noOfComponents;\n"
180 "uniform sampler2D in_depthSampler;\n"
182 "// Camera position\n"
183 "uniform vec3 in_cameraPos;\n";
188 toShaderStr <<
"uniform sampler2D in_noiseSampler;\n";
193 const int numTransf = (numInputs > 1) ? numInputs + 1 : 1;
194 toShaderStr <<
"uniform mat4 in_volumeMatrix[" << numTransf
196 "uniform mat4 in_inverseVolumeMatrix["
199 "uniform mat4 in_textureDatasetMatrix["
202 "uniform mat4 in_inverseTextureDatasetMatrix["
205 "uniform mat4 in_textureToEye["
208 "uniform vec3 in_texMin["
211 "uniform vec3 in_texMax["
214 "uniform mat4 in_cellToPoint["
215 << numTransf <<
"];\n";
217 toShaderStr <<
"// view and model matrices\n"
218 "uniform mat4 in_projectionMatrix;\n"
219 "uniform mat4 in_inverseProjectionMatrix;\n"
220 "uniform mat4 in_modelViewMatrix;\n"
221 "uniform mat4 in_inverseModelViewMatrix;\n"
222 "in mat4 ip_inverseTextureDataAdjusted;\n"
225 "uniform vec3 in_cellStep["
226 << numInputs <<
"];\n";
231 toShaderStr <<
"mat4 g_eyeToTexture = in_inverseTextureDatasetMatrix[0] *"
232 " in_inverseVolumeMatrix[0] * in_inverseModelViewMatrix;\n";
235 if (inputs[0].Volume->GetProperty() && inputs[0].Volume->GetProperty()->GetShade() &&
236 !defaultLighting && totalNumberOfLights > 0)
238 toShaderStr <<
"mat4 g_texToView = in_modelViewMatrix * in_volumeMatrix[0] *"
239 "in_textureDatasetMatrix[0];\n";
242 toShaderStr <<
"uniform vec2 in_scalarsRange[" << numInputs * 4
244 "uniform vec3 in_cellSpacing["
248 "// Sample distance\n"
249 "uniform float in_sampleDistance;\n"
252 "uniform vec2 in_windowLowerLeftCorner;\n"
253 "uniform vec2 in_inverseOriginalWindowSize;\n"
254 "uniform vec2 in_inverseWindowSize;\n"
255 "uniform vec3 in_textureExtentsMax;\n"
256 "uniform vec3 in_textureExtentsMin;\n"
258 "// Material and lighting\n"
259 "uniform vec3 in_diffuse[4];\n"
260 "uniform vec3 in_ambient[4];\n"
261 "uniform vec3 in_specular[4];\n"
262 "uniform float in_shininess[4];\n"
265 "vec3 g_rayJitter = vec3(0.0);\n"
267 "uniform vec2 in_averageIPRange;\n";
269 toShaderStr <<
"vec4 g_eyePosObjs[" << numInputs <<
"];\n";
271 const bool hasGradientOpacity = HasGradientOpacity(inputs);
272 if (totalNumberOfLights > 0 || hasGradientOpacity)
274 toShaderStr <<
"uniform bool in_twoSidedLighting;\n";
279 toShaderStr << R
"***(
280 uniform float in_giReach;
281 uniform float in_anisotropy;
282 uniform float in_volumetricScatteringBlending;
287 if (totalNumberOfLights > 0)
289 std::string totalLights = std::to_string(totalNumberOfLights);
290 std::string positionalLights = std::to_string(numberPositionalLights);
292 if (!defaultLighting)
294 toShaderStr <<
"#define TOTAL_NUMBER_LIGHTS " << totalLights
296 "#define NUMBER_POS_LIGHTS "
299 "vec4 g_fragWorldPos;\n"
300 "uniform vec3 in_lightAmbientColor[TOTAL_NUMBER_LIGHTS];\n"
301 "uniform vec3 in_lightDiffuseColor[TOTAL_NUMBER_LIGHTS];\n"
302 "uniform vec3 in_lightSpecularColor[TOTAL_NUMBER_LIGHTS];\n"
303 "uniform vec3 in_lightDirection[TOTAL_NUMBER_LIGHTS];\n";
304 if (numberPositionalLights > 0)
306 toShaderStr <<
"uniform vec3 in_lightPosition[NUMBER_POS_LIGHTS];\n"
307 "uniform vec3 in_lightAttenuation[NUMBER_POS_LIGHTS];\n"
308 "uniform float in_lightConeAngle[NUMBER_POS_LIGHTS];\n"
309 "uniform float in_lightExponent[NUMBER_POS_LIGHTS];\n";
314 toShaderStr <<
"vec3 g_lightDirectionTex[TOTAL_NUMBER_LIGHTS];";
316 if (numberPositionalLights > 0)
318 toShaderStr <<
"vec3 g_lightPositionTex[NUMBER_POS_LIGHTS];";
324 toShaderStr <<
"uniform vec3 in_lightAmbientColor[1];\n"
325 "uniform vec3 in_lightDiffuseColor[1];\n"
326 "uniform vec3 in_lightSpecularColor[1];\n"
327 "vec4 g_lightPosObj["
337 << numInputs <<
"];\n";
341 if (noOfComponents > 1 && independentComponents)
343 toShaderStr <<
"uniform vec4 in_componentWeight;\n";
349 toShaderStr <<
"uniform sampler2D in_depthPassSampler;\n";
354 toShaderStr <<
"#if NUMBER_OF_CONTOURS\n"
355 "uniform float in_isosurfacesValues[NUMBER_OF_CONTOURS];\n"
357 "int findIsoSurfaceIndex(float scalar, float array[NUMBER_OF_CONTOURS+2])\n"
359 " int index = NUMBER_OF_CONTOURS >> 1;\n"
360 " while (scalar > array[index]) ++index;\n"
361 " while (scalar < array[index]) --index;\n"
368 vtkVolume* vol = inputs.begin()->second.Volume;
371 if (func && func->
IsA(
"vtkPlane"))
374 <<
"uniform vec3 in_slicePlaneOrigin;\n"
375 "uniform vec3 in_slicePlaneNormal;\n"
376 "vec3 g_intersection;\n"
378 "float intersectRayPlane(vec3 rayOrigin, vec3 rayDir)\n"
380 " vec4 planeNormal = in_inverseVolumeMatrix[0] * vec4(in_slicePlaneNormal, 0.0);\n"
381 " float denom = dot(planeNormal.xyz, rayDir);\n"
382 " if (abs(denom) > 1e-6)\n"
384 " vec4 planeOrigin = in_inverseVolumeMatrix[0] * vec4(in_slicePlaneOrigin, 1.0);\n"
385 " return dot(planeOrigin.xyz - rayOrigin, planeNormal.xyz) / denom;\n"
392 return toShaderStr.str();
400 vtkVolume* vol = inputs.begin()->second.Volume;
401 const int numInputs =
static_cast<int>(inputs.size());
403 std::ostringstream shaderStr;
409 \n vec2 fragTexCoord2 = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
410 \n in_inverseWindowSize;\
411 \n vec4 depthValue = texture2D(in_depthPassSampler, fragTexCoord2);\
412 \n vec4 rayOrigin = WindowToNDC(gl_FragCoord.x, gl_FragCoord.y, depthValue.x);\
414 \n // From normalized device coordinates to eye coordinates.\
415 \n // in_projectionMatrix is inversed because of way VT\
416 \n // From eye coordinates to texture coordinates\
417 \n rayOrigin = in_inverseTextureDatasetMatrix[0] *\
418 \n in_inverseVolumeMatrix[0] *\
419 \n in_inverseModelViewMatrix *\
420 \n in_inverseProjectionMatrix *\
422 \n rayOrigin /= rayOrigin.w;\
423 \n g_rayOrigin = rayOrigin.xyz;";
428 \n // Get the 3D texture coordinates for lookup into the in_volume dataset\
429 \n g_rayOrigin = ip_textureCoords.xyz;";
434 \n // Eye position in dataset space\
435 \n g_eyePosObj = in_inverseVolumeMatrix[0] * vec4(in_cameraPos, 1.0);";
436 for (
int i = 0; i < numInputs; ++i)
441 << i <<
"] = in_inverseVolumeMatrix[" << (numInputs > 1 ? i + 1 : i)
442 <<
"] * vec4(in_cameraPos, 1.0);";
445 \n // Getting the ray marching direction (in dataset space)\
446 \n vec3 rayDir = computeRayDirection();\
448 \n // 2D Texture fragment coordinates [0,1] from fragment coordinates.\
449 \n // The frame buffer texture has the size of the plain buffer but \
450 \n // we use a fraction of it. The texture coordinate is less than 1 if\
451 \n // the reduction factor is less than 1.\
452 \n // Device coordinates are between -1 and 1. We need texture\
453 \n // coordinates between 0 and 1. The in_depthSampler\
454 \n // buffer has the original size buffer.\
455 \n vec2 fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
456 \n in_inverseWindowSize;\
458 \n // Multiply the raymarching direction with the step size to get the\
459 \n // sub-step size we need to take at each raymarching step\
460 \n g_dirStep = (ip_inverseTextureDataAdjusted *\
461 \n vec4(rayDir, 0.0)).xyz * in_sampleDistance;\
462 \n g_lengthStep = length(g_dirStep);\
466 \n float jitterValue = 0.0;\
475 \n jitterValue = texture2D(in_noiseSampler, gl_FragCoord.xy /\
476 vec2(textureSize(in_noiseSampler, 0))).x;\
477 \n g_rayJitter = g_dirStep * jitterValue;\
483 \n g_rayJitter = g_dirStep;\
487 \n g_rayOrigin += g_rayJitter;\
492 \n // Flag to determine if voxel should be considered for the rendering\
498 \n // Light position in dataset space";
499 for (
int i = 0; i < numInputs; ++i)
504 << i <<
"] = (in_inverseVolumeMatrix[" << (numInputs > 1 ? i + 1 : i) <<
"] *\
505 \n vec4(in_cameraPos, 1.0));\
507 << i <<
"] = normalize(g_lightPosObj[" << i <<
"].xyz - ip_vertexPos);\
509 << i <<
"] = normalize(g_eyePosObjs[" << i <<
"].xyz - ip_vertexPos);\
511 << i <<
"] = normalize(g_ldir[" << i <<
"] + g_vdir[" << i <<
"]);";
515 return shaderStr.str();
525 \n g_skip = false;");
531 if (blankPoints || blankCells)
534 \n // Check whether the neighboring points/cells are blank.\
535 \n // Note the half cellStep because texels are point centered.\
536 \n vec3 xvec = vec3(in_cellStep[0].x/2.0, 0.0, 0.0);\
537 \n vec3 yvec = vec3(0.0, in_cellStep[0].y/2.0, 0.0);\
538 \n vec3 zvec = vec3(0.0, 0.0, in_cellStep[0].z/2.0);\
539 \n vec3 texPosPVec[3];\
540 \n texPosPVec[0] = g_dataPos + xvec;\
541 \n texPosPVec[1] = g_dataPos + yvec;\
542 \n texPosPVec[2] = g_dataPos + zvec;\
543 \n vec3 texPosNVec[3];\
544 \n texPosNVec[0] = g_dataPos - xvec;\
545 \n texPosNVec[1] = g_dataPos - yvec;\
546 \n texPosNVec[2] = g_dataPos - zvec;\
547 \n vec4 blankValue = texture3D(in_blanking, g_dataPos);\
548 \n vec4 blankValueXP = texture3D(in_blanking, texPosPVec[0]);\
549 \n vec4 blankValueYP = texture3D(in_blanking, texPosPVec[1]);\
550 \n vec4 blankValueZP = texture3D(in_blanking, texPosPVec[2]);\
551 \n vec4 blankValueXN = texture3D(in_blanking, texPosNVec[0]);\
552 \n vec4 blankValueYN = texture3D(in_blanking, texPosNVec[1]);\
553 \n vec4 blankValueZN = texture3D(in_blanking, texPosNVec[2]);\
554 \n vec3 blankValuePx;\
555 \n blankValuePx[0] = blankValueXP.x;\
556 \n blankValuePx[1] = blankValueYP.x;\
557 \n blankValuePx[2] = blankValueZP.x;\
558 \n vec3 blankValuePy;\
559 \n blankValuePy[0] = blankValueXP.y;\
560 \n blankValuePy[1] = blankValueYP.y;\
561 \n blankValuePy[2] = blankValueZP.y;\
562 \n vec3 blankValueNx;\
563 \n blankValueNx[0] = blankValueXN.x;\
564 \n blankValueNx[1] = blankValueYN.x;\
565 \n blankValueNx[2] = blankValueZN.x;\
566 \n vec3 blankValueNy;\
567 \n blankValueNy[0] = blankValueXN.y;\
568 \n blankValueNy[1] = blankValueYN.y;\
569 \n blankValueNy[2] = blankValueZN.y;\
574 \n // If the current or neighboring points\
575 \n // (that belong to cells that share this texel) are blanked,\
576 \n // skip the texel. In other words, if point 1 were blank,\
577 \n // texels 0, 1 and 2 would have to be skipped.\
578 \n if (blankValue.x > 0.0 ||\
579 \n any(greaterThan(blankValueNx, vec3(0.0))) ||\
580 \n any(greaterThan(blankValuePx, vec3(0.0))))\
582 \n // skip this texel\
589 \n // If the current or previous cells (that share this texel)\
590 \n // are blanked, skip the texel. In other words, if cell 1\
591 \n // is blanked, texels 1 and 2 would have to be skipped.\
592 \n else if (blankValue.y > 0.0 ||\
593 \n any(greaterThan(blankValuePy, vec3(0.0))) ||\
594 \n any(greaterThan(blankValueNy, vec3(0.0))))\
596 \n // skip this texel\
605 \n // If the current or previous cells (that share this texel)\
606 \n // are blanked, skip the texel. In other words, if cell 1\
607 \n // is blanked, texels 1 and 2 would have to be skipped.\
608 \n if (blankValue.x > 0.0 ||\
609 \n any(greaterThan(blankValueNx, vec3(0.0))) ||\
610 \n any(greaterThan(blankValuePx, vec3(0.0))))\
612 \n // skip this texel\
622 \n g_dataPos = g_intersection;\
638 int independentComponents, std::map<int, std::string> gradientTableMap)
641 std::ostringstream ss;
642 if (volProperty->HasGradientOpacity())
644 ss <<
"uniform sampler2D " << ArrayBaseName(gradientTableMap[0]) <<
"[" << noOfComponents
647 bool useLabelGradientOpacity =
648 (volProperty->HasLabelGradientOpacity() && (noOfComponents == 1 || !independentComponents));
649 if (useLabelGradientOpacity)
651 ss <<
"uniform sampler2D in_labelMapGradientOpacity;\n";
656 if (volProperty->HasGradientOpacity() && noOfComponents > 0)
658 if (noOfComponents == 1 || !independentComponents)
661 \nfloat computeGradientOpacity(vec4 grad)\
663 \n return texture2D(" +
664 gradientTableMap[0] +
", vec2(grad.w, 0.0)).r;\
670 \nfloat computeGradientOpacity(vec4 grad, int component)\
673 for (
int i = 0; i < noOfComponents; ++i)
675 std::ostringstream toString;
678 \n if (component == " +
679 toString.str() +
")");
683 \n return texture2D(" +
684 gradientTableMap[i] +
", vec2(grad.w, 0.0)).r;\
693 if (useLabelGradientOpacity)
696 \nfloat computeGradientOpacityForLabel(vec4 grad, float label)\
698 \n return texture2D(in_labelMapGradientOpacity, vec2(grad.w, label)).r;\
709 const bool hasLighting = HasLighting(inputs);
710 const bool hasGradientOp = HasGradientOpacity(inputs);
713 if (hasLighting || hasGradientOp)
716 "// c is short for component\n"
717 "vec4 computeGradient(in vec3 texPos, in int c, in sampler3D volume,in int index)\n"
719 " // Approximate Nabla(F) derivatives with central differences.\n"
720 " vec3 g1; // F_front\n"
721 " vec3 g2; // F_back\n"
722 " vec3 xvec = vec3(in_cellStep[index].x, 0.0, 0.0);\n"
723 " vec3 yvec = vec3(0.0, in_cellStep[index].y, 0.0);\n"
724 " vec3 zvec = vec3(0.0, 0.0, in_cellStep[index].z);\n"
725 " vec3 texPosPvec[3];\n"
726 " texPosPvec[0] = texPos + xvec;\n"
727 " texPosPvec[1] = texPos + yvec;\n"
728 " texPosPvec[2] = texPos + zvec;\n"
729 " vec3 texPosNvec[3];\n"
730 " texPosNvec[0] = texPos - xvec;\n"
731 " texPosNvec[1] = texPos - yvec;\n"
732 " texPosNvec[2] = texPos - zvec;\n"
733 " g1.x = texture3D(volume, vec3(texPosPvec[0]))[c];\n"
734 " g1.y = texture3D(volume, vec3(texPosPvec[1]))[c];\n"
735 " g1.z = texture3D(volume, vec3(texPosPvec[2]))[c];\n"
736 " g2.x = texture3D(volume, vec3(texPosNvec[0]))[c];\n"
737 " g2.y = texture3D(volume, vec3(texPosNvec[1]))[c];\n"
738 " g2.z = texture3D(volume, vec3(texPosNvec[2]))[c];\n"
743 std::string(
" vec4 g1ObjDataPos[3], g2ObjDataPos[3];\n"
744 " for (int i = 0; i < 3; ++i)\n"
746 " g1ObjDataPos[i] = clip_texToObjMat * vec4(texPosPvec[i], 1.0);\n"
747 " if (g1ObjDataPos[i].w != 0.0)\n"
749 " g1ObjDataPos[i] /= g1ObjDataPos[i].w;\n"
751 " g2ObjDataPos[i] = clip_texToObjMat * vec4(texPosNvec[i], 1.0);\n"
752 " if (g2ObjDataPos[i].w != 0.0)\n"
754 " g2ObjDataPos[i] /= g2ObjDataPos[i].w;\n"
758 " for (int i = 0; i < clip_numPlanes && !g_skip; i = i + 6)\n"
760 " vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\n"
761 " in_clippingPlanes[i + 2],\n"
762 " in_clippingPlanes[i + 3]);\n"
763 " vec3 planeNormal = normalize(vec3(in_clippingPlanes[i + 4],\n"
764 " in_clippingPlanes[i + 5],\n"
765 " in_clippingPlanes[i + 6]));\n"
766 " for (int j = 0; j < 3; ++j)\n"
768 " if (dot(vec3(planeOrigin - g1ObjDataPos[j].xyz), planeNormal) > 0)\n"
770 " g1[j] = in_clippedVoxelIntensity;\n"
772 " if (dot(vec3(planeOrigin - g2ObjDataPos[j].xyz), planeNormal) > 0)\n"
774 " g2[j] = in_clippedVoxelIntensity;\n"
780 shaderStr +=
std::string(
" // Apply scale and bias to the fetched values.\n"
781 " g1 = g1 * in_volume_scale[index][c] + in_volume_bias[index][c];\n"
782 " g2 = g2 * in_volume_scale[index][c] + in_volume_bias[index][c];\n"
787 std::string(
" // Central differences: (F_front - F_back) / 2h\n"
788 " // This version of computeGradient() is only used for lighting\n"
789 " // calculations (only direction matters), hence the difference is\n"
790 " // not scaled by 2h and a dummy gradient mag is returned (-1.).\n"
791 " return vec4((g1 - g2) / in_cellSpacing[index], -1.0);\n"
797 " // Scale values the actual scalar range.\n"
798 " float range = in_scalarsRange[4*index+c][1] - in_scalarsRange[4*index+c][0];\n"
799 " g1 = in_scalarsRange[4*index+c][0] + range * g1;\n"
800 " g2 = in_scalarsRange[4*index+c][0] + range * g2;\n"
802 " // Central differences: (F_front - F_back) / 2h\n"
805 " float avgSpacing = (in_cellSpacing[index].x +\n"
806 " in_cellSpacing[index].y + in_cellSpacing[index].z) / 3.0;\n"
807 " vec3 aspect = in_cellSpacing[index] * 2.0 / avgSpacing;\n"
809 " float grad_mag = length(g2);\n"
811 " // Handle normalizing with grad_mag == 0.0\n"
812 " g2 = grad_mag > 0.0 ? normalize(g2) : vec3(0.0);\n"
814 " // Since the actual range of the gradient magnitude is unknown,\n"
815 " // assume it is in the range [0, 0.25 * dataRange].\n"
816 " range = range != 0 ? range : 1.0;\n"
817 " grad_mag = grad_mag / (0.25 * range);\n"
818 " grad_mag = clamp(grad_mag, 0.0, 1.0);\n"
820 " return vec4(g2.xyz, grad_mag);\n"
827 "vec4 computeGradient(in vec3 texPos, in int c, in sampler3D volume, in int index)\n"
829 " return vec4(0.0);\n"
842 for(int i=0; i<TOTAL_NUMBER_LIGHTS; i++)
844 g_lightDirectionTex[i] = (g_eyeToTexture * vec4(-in_lightDirection[i], 0.0)).xyz;
848 if (numberPositionalLights > 0)
851 for(int i=0; i<NUMBER_POS_LIGHTS; i++)
853 g_lightPositionTex[i] = (g_eyeToTexture * vec4(in_lightPosition[i], 1.0)).xyz;
863 int independentComponents, std::map<int, std::string> opacityTableMap,
int useGradient)
867 bool severalIndpt = noOfComponents > 1 && independentComponents;
869 ?
"vec4 computeRGBAWithGrad(vec4 scalar, vec4 grad, int component)\n"
870 :
"vec4 computeRGBAWithGrad(vec4 scalar, vec4 grad)\n";
879 "vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
880 "for (int i = 0; i < 4; ++i)\n"
882 " yscalar[i] = yscalar[i] * in_transfer2DYAxis_scale[i] + in_transfer2DYAxis_bias[i];\n"
886 for (
int i = 0; i < noOfComponents; ++i)
892 :
std::string(
"yscalar[") + std::to_string(i) +
"]");
894 functionBody +=
" if(component == " + std::to_string(i) +
897 " return texture2D(" +
898 opacityTableMap[i] +
",\n" +
" vec2(scalar[" + std::to_string(i) +
"], " + secondAxis +
903 else if (noOfComponents == 2 && !independentComponents)
905 std::string secondAxis(useGradient ?
"grad.w" :
"yscalar.y");
907 functionBody +=
" return texture2D(" + opacityTableMap[0] +
910 secondAxis +
"));\n";
918 functionBody +=
" return texture2D(" + opacityTableMap[0] +
920 " vec2(scalar.a, grad.w));\n";
926 " vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
927 " yscalar.r = yscalar.r * in_transfer2DYAxis_scale.r + in_transfer2DYAxis_bias.r;\n"
928 " yscalar = vec4(yscalar.r);\n"
929 " return texture2D(" +
932 " vec2(scalar.a, yscalar.w));\n";
936 resStr = functionSignature +
"{\n" + functionBody +
"}\n";
944 int independentComponents,
int useGradYAxis,
std::string position,
bool requestColor =
false)
950 if (inputs.size() > 1)
953 const bool hasGradOp = ::HasGradientOpacity(inputs);
954 resStr +=
" opacity = computeOpacity(vec4(scalar), opacityTF);\n";
959 resStr +=
std::string(
" gradient = computeGradient(") + position +
", c, volume, index);\n";
960 resStr +=
" opacity *= computeGradientOpacity(gradient, gradTF);\n";
966 vtkGenericWarningMacro(<<
"ComputeOpacityEvaluationCall was called with requestColor, but "
967 "MultiVolume does not support this option yet.");
980 bool indpComps = (noOfComponents > 1 && independentComponents);
990 resStr +=
std::string(
" opacity = computeOpacity(vec4(scalar)") + compArgument +
993 if (hasGradOp || useLabelGradientOpacity)
995 resStr +=
std::string(
" gradient = computeGradient(") + position +
997 " if(gradient.w >= 0.0) {\n") +
998 (hasGradOp ? (
std::string(
" opacity *= computeGradientOpacity(gradient") +
999 compArgument +
")" + compWeights +
";\n")
1002 + (useLabelGradientOpacity
1003 ? (std::string(
" opacity *= computeGradientOpacityForLabel(gradient, label);\n"))
1006 + std::string(
" }\n");
1012 " color = texture2D(" + inputs[0].RGBTablesMap[0] +
", vec2(scalar, 0.0)).xyz;\n";
1021 std::string(
" gradient = computeGradient(") + position +
", c, volume, index);\n";
1023 resStr +=
std::string(
" vec4 lutRes = computeRGBAWithGrad(vec4(scalar), gradient") +
1026 resStr +=
" opacity = lutRes.a;\n";
1030 resStr +=
" color = lutRes.xyz\n";
1041 int independentComponents,
int useGradYAxis)
1043 const bool hasLighting = ::HasLighting(inputs);
1044 const bool hasGradientOp = ::HasGradientOpacity(inputs);
1048 if (inputs.size() > 1)
1053 "vec4 computeDensityGradient(in vec3 texPos, in int c, in sampler3D volume, "
1054 "const in sampler2D opacityTF, const in sampler2D gradTF, in int index, float label)\n");
1059 std::string(
"vec4 computeDensityGradient(in vec3 texPos, in int c, in sampler3D volume, "
1060 "const in sampler2D opacityTF, in int index, float label)\n");
1065 functionSignature =
std::string(
"vec4 computeDensityGradient(in vec3 texPos, in int c, in "
1066 "sampler3D volume, in int index, float label)\n");
1070 if (hasLighting || hasGradientOp)
1076 static const std::array<std::pair<const char*, const char*>, 6> results_texPos = { {
1077 {
" g1.x",
"texPosPvec[0]" },
1078 {
" g1.y",
"texPosPvec[1]" },
1079 {
" g1.z",
"texPosPvec[2]" },
1080 {
" g2.x",
"texPosNvec[0]" },
1081 {
" g2.y",
"texPosNvec[1]" },
1082 {
" g2.z",
"texPosNvec[2]" },
1085 shaderStr +=
std::string(
"// c is short for component\n") + functionSignature +
1087 " // Approximate Nabla(F) derivatives with central differences.\n"
1088 " vec3 g1; // F_front\n"
1089 " vec3 g2; // F_back\n"
1090 " vec3 xvec = vec3(in_cellStep[index].x, 0.0, 0.0);\n"
1091 " vec3 yvec = vec3(0.0, in_cellStep[index].y, 0.0);\n"
1092 " vec3 zvec = vec3(0.0, 0.0, in_cellStep[index].z);\n"
1093 " vec3 texPosPvec[3];\n"
1094 " texPosPvec[0] = texPos + xvec;\n"
1095 " texPosPvec[1] = texPos + yvec;\n"
1096 " texPosPvec[2] = texPos + zvec;\n"
1097 " vec3 texPosNvec[3];\n"
1098 " texPosNvec[0] = texPos - xvec;\n"
1099 " texPosNvec[1] = texPos - yvec;\n"
1100 " texPosNvec[2] = texPos - zvec;\n"
1106 for (
auto& gradComp : results_texPos)
1110 mapper, inputs, noOfComponents, independentComponents, useGradYAxis, gradComp.second);
1111 shaderStr +=
std::string(
" scalar = texture3D(volume,") + gradComp.second +
1113 " scalar = scalar * in_volume_scale[index][c] + in_volume_bias[index][c];\n") +
1114 opacityTFcall + gradComp.first +
" = opacity;\n";
1120 std::string(
" vec4 g1ObjDataPos[3], g2ObjDataPos[3];\n"
1121 " for (int i = 0; i < 3; ++i)\n"
1123 " g1ObjDataPos[i] = clip_texToObjMat * vec4(texPosPvec[i], 1.0);\n"
1124 " if (g1ObjDataPos[i].w != 0.0)\n"
1126 " g1ObjDataPos[i] /= g1ObjDataPos[i].w;\n"
1128 " g2ObjDataPos[i] = clip_texToObjMat * vec4(texPosNvec[i], 1.0);\n"
1129 " if (g2ObjDataPos[i].w != 0.0)\n"
1131 " g2ObjDataPos[i] /= g2ObjDataPos[i].w;\n"
1135 " for (int i = 0; i < clip_numPlanes && !g_skip; i = i + 6)\n"
1137 " vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\n"
1138 " in_clippingPlanes[i + 2],\n"
1139 " in_clippingPlanes[i + 3]);\n"
1140 " vec3 planeNormal = normalize(vec3(in_clippingPlanes[i + 4],\n"
1141 " in_clippingPlanes[i + 5],\n"
1142 " in_clippingPlanes[i + 6]));\n"
1143 " for (int j = 0; j < 3; ++j)\n"
1145 " if (dot(vec3(planeOrigin - g1ObjDataPos[j].xyz), planeNormal) > 0)\n"
1147 " g1[j] = in_clippedVoxelIntensity;\n"
1149 " if (dot(vec3(planeOrigin - g2ObjDataPos[j].xyz), planeNormal) > 0)\n"
1151 " g2[j] = in_clippedVoxelIntensity;\n"
1161 std::string(
" // Central differences: (F_front - F_back) / 2h\n"
1162 " // This version of computeGradient() is only used for lighting\n"
1163 " // calculations (only direction matters), hence the difference is\n"
1164 " // not scaled by 2h and a dummy gradient mag is returned (-1.).\n"
1165 " return vec4((g1 - g2) / in_cellSpacing[index], -1.0);\n"
1171 " // Scale values the actual scalar range.\n"
1172 " float range = in_scalarsRange[4*index+c][1] - in_scalarsRange[4*index+c][0];\n"
1173 " g1 = in_scalarsRange[4*index+c][0] + range * g1;\n"
1174 " g2 = in_scalarsRange[4*index+c][0] + range * g2;\n"
1176 " // Central differences: (F_front - F_back) / 2h\n"
1179 " float avgSpacing = (in_cellSpacing[index].x +\n"
1180 " in_cellSpacing[index].y + in_cellSpacing[index].z) / 3.0;\n"
1181 " vec3 aspect = in_cellSpacing[index] * 2.0 / avgSpacing;\n"
1183 " float grad_mag = length(g2);\n"
1185 " // Handle normalizing with grad_mag == 0.0\n"
1186 " g2 = grad_mag > 0.0 ? normalize(g2) : vec3(0.0);\n"
1188 " // Since the actual range of the gradient magnitude is unknown,\n"
1189 " // assume it is in the range [0, 0.25 * dataRange].\n"
1190 " range = range != 0 ? range : 1.0;\n"
1191 " grad_mag = grad_mag / (0.25 * range);\n"
1192 " grad_mag = clamp(grad_mag, 0.0, 1.0);\n"
1194 " return vec4(g2.xyz, grad_mag);\n"
1200 shaderStr += functionSignature +
1202 " return vec4(0.0);\n"
1219 float phase_function(float cos_angle)
1228 float g_anisotropy2 = in_anisotropy * in_anisotropy;
1230 float phase_function(float cos_angle)
1232 float d = 1.0 + g_anisotropy2 - 2.0 * in_anisotropy * cos_angle;
1233 return (1.0 - g_anisotropy2) / (d * sqrt(d));
1243 vtkVolume* vol,
int noOfComponents,
int independentComponents,
int totalNumberOfLights,
1244 int numberPositionalLights,
bool defaultLighting)
1249 \nvec4 computeLighting(vec4 color, int component, float label)\
1251 \n vec4 finalColor = vec4(0.0);\n");
1254 int const shadeReqd = volProperty->
GetShade() &&
1261 bool const volumetricShadow = glMapper->GetVolumetricScatteringBlending() > 0.0;
1263 ?
"\n vol_shadow = volumeShadow(g_dataPos, tex_light.xyz, 0.0, component, in_volume[0], "
1267 volumetricShadow ?
"\n float vol_shadow = 1.0;\n vec4 tex_light = vec4(0.0);\n" :
"\n";
1272 if (glMapper->GetComputeNormalFromOpacity())
1276 std::string(
" vec4 shading_gradient = computeDensityGradient(g_dataPos, component, "
1277 "in_volume[0], 0, label);\n");
1283 " vec4 shading_gradient = computeGradient(g_dataPos, component, in_volume[0], 0);\n");
1291 if (!shadeReqd || glMapper->GetComputeNormalFromOpacity())
1294 std::string(
" vec4 gradient = computeGradient(g_dataPos, component, in_volume[0], 0);\n");
1299 shaderStr +=
std::string(
" vec4 gradient = shading_gradient;\n");
1305 if (defaultLighting)
1308 vec3 diffuse = vec3(0.0);
1309 vec3 specular = vec3(0.0);
1310 vec3 normal = shading_gradient.xyz;
1311 float normalLength = length(normal);
1312 if (normalLength > 0.0)
1314 normal = normalize(normal);
1318 normal = vec3(0.0, 0.0, 0.0);
1320 // XXX: normal is oriented inside the volume, so we take -g_ldir/-g_vdir
1321 float nDotL = dot(normal, -g_ldir[0]);
1322 vec3 r = normalize(2.0 * nDotL * normal + g_ldir[0]);
1323 float vDotR = dot(r, -g_vdir[0]);
1324 if (nDotL < 0.0 && in_twoSidedLighting)
1330 diffuse = nDotL * in_diffuse[component] *
1331 in_lightDiffuseColor[0] * color.rgb;
1332 vDotR = max(vDotR, 0.0);
1333 specular = pow(vDotR, in_shininess[component]) *
1334 in_specular[component] *
1335 in_lightSpecularColor[0];
1337 // For the headlight, ignore the light's ambient color
1338 // for now as it is causing the old mapper tests to fail
1339 finalColor.xyz = in_ambient[component] * color.rgb +
1344 else if (totalNumberOfLights > 0)
1347 g_fragWorldPos = g_texToView * vec4(g_dataPos, 1.0);
1348 if (g_fragWorldPos.w != 0.0)
1350 g_fragWorldPos /= g_fragWorldPos.w;
1352 vec3 viewDirection = normalize(-g_fragWorldPos.xyz);
1353 vec3 ambient = vec3(0,0,0);
1354 vec3 diffuse = vec3(0,0,0);
1355 vec3 specular = vec3(0,0,0);
1356 vec3 vertLightDirection;
1357 vec3 normal = normalize((in_textureToEye[0] * vec4(shading_gradient.xyz, 0.0)).xyz);
1361 if (numberPositionalLights > 0)
1364 for (int posNum = 0; posNum < NUMBER_POS_LIGHTS; posNum++)
1366 float attenuation = 1.0;
1367 lightDir = in_lightDirection[posNum];
1368 vertLightDirection = (g_fragWorldPos.xyz - in_lightPosition[posNum]);
1369 float distance = length(vertLightDirection);
1370 vertLightDirection = normalize(vertLightDirection);
1372 (in_lightAttenuation[posNum].x
1373 + in_lightAttenuation[posNum].y * distance
1374 + in_lightAttenuation[posNum].z * distance * distance);
1375 // per OpenGL standard cone angle is 90 or less for a spot light
1376 if (in_lightConeAngle[posNum] <= 90.0)
1378 float coneDot = dot(vertLightDirection, lightDir);
1379 // if inside the cone
1380 if (coneDot >= cos(radians(in_lightConeAngle[posNum])))
1382 attenuation = attenuation * pow(coneDot, in_lightExponent[posNum]);
1390 float nDotL = dot(normal, vertLightDirection);
1391 if (nDotL < 0.0 && in_twoSidedLighting)
1397 float df = max(0.0, attenuation * nDotL);
1398 diffuse += (df * in_lightDiffuseColor[posNum]);
1399 vec3 r = normalize(2.0 * nDotL * normal - vertLightDirection);
1400 float rDotV = dot(-viewDirection, r);
1401 if (rDotV < 0.0 && in_twoSidedLighting)
1407 float sf = attenuation * pow(rDotV, in_shininess[component]);
1408 specular += (sf * in_lightSpecularColor[posNum]);
1411 ambient += in_lightAmbientColor[posNum];
1417 for (int dirNum = NUMBER_POS_LIGHTS; dirNum < TOTAL_NUMBER_LIGHTS; dirNum++)
1419 vertLightDirection = in_lightDirection[dirNum];
1420 float nDotL = dot(normal, vertLightDirection);
1421 if (nDotL < 0.0 && in_twoSidedLighting)
1427 float df = max(0.0, nDotL);
1428 diffuse += (df * in_lightDiffuseColor[dirNum]);
1429 vec3 r = normalize(2.0 * nDotL * normal - vertLightDirection);
1430 float rDotV = dot(-viewDirection, r);
1433 float sf = pow(rDotV, in_shininess[component]);
1434 specular += (sf * in_lightSpecularColor[dirNum]);
1437 ambient += in_lightAmbientColor[dirNum];
1439 finalColor.xyz = in_ambient[component] * ambient +
1440 in_diffuse[component] * diffuse * color.rgb +
1441 in_specular[component] * specular;
1448 shaderStr +=
std::string(
"\n finalColor = vec4(color.rgb, 0.0);");
1451 if (glMapper->GetVolumetricScatteringBlending() > 0.0 && totalNumberOfLights > 0)
1454 float vsBlend = glMapper->GetVolumetricScatteringBlending();
1456 (vsBlend < 1.0 ?
"2.0 * in_volumetricScatteringBlending * exp( - 2.0 * "
1457 "in_volumetricScatteringBlending * shading_gradient.w * color.a)"
1458 :
"2.0 * (1.0 - in_volumetricScatteringBlending) * exp( - 2.0 * "
1459 "in_volumetricScatteringBlending * shading_gradient.w * color.a) + 2.0 * "
1460 "in_volumetricScatteringBlending - 1.0") +
1467 "vec3 view_tdir = normalize((g_eyeToTexture * vec4(viewDirection, 0.0)).xyz);\n")) +
1469 vec3 secondary_contrib = vec3(0.0);
1470 vec3 tex_light = vec3(0.0);
1471 shading_gradient.w = length(shading_gradient.xyz);
1472 vec3 diffuse_light = vec3(0.0);
1473 float attenuation = 0.0;
1474 float vol_shadow = 0.0;
1478 if (defaultLighting)
1481 tex_light = (in_inverseTextureDatasetMatrix[0] * in_inverseVolumeMatrix[0] * vec4(in_cameraPos, 1.0)).xyz;
1482 phase = phase_function(-1); // always angle of pi
1483 vol_shadow = volumeShadow(g_dataPos, tex_light, 1.0, component, in_volume[0], 0, label);
1484 secondary_contrib += vol_shadow * phase * color.rgb * in_diffuse[component] * in_lightDiffuseColor[0];
1485 secondary_contrib += in_ambient[component] * in_lightAmbientColor[0];
1490 if (numberPositionalLights > 0)
1493 float dist_light = 0.0;
1494 for(int posNum = 0; posNum < NUMBER_POS_LIGHTS; posNum++)
1496 tex_light = g_lightPositionTex[posNum];
1497 vec3 light_vert = g_fragWorldPos.xyz - in_lightPosition[posNum];
1498 dist_light = length(light_vert);
1499 float light_angle = dot(normalize(light_vert), normalize(in_lightDirection[posNum]));
1500 phase = phase_function(dot(normalize(g_dataPos - tex_light), view_tdir));
1502 (in_lightAttenuation[posNum].x
1503 + in_lightAttenuation[posNum].y * dist_light
1504 + in_lightAttenuation[posNum].z * dist_light * dist_light);
1505 attenuation *= max(0.0, sign(light_angle - cos(radians(in_lightConeAngle[posNum]))))
1506 * pow(light_angle, in_lightExponent[posNum]);
1507 vol_shadow = volumeShadow(g_dataPos, tex_light, 1.0, component, in_volume[0], 0, label);
1508 secondary_contrib += vol_shadow * phase * attenuation * color.rgb * in_diffuse[component] * in_lightDiffuseColor[posNum];
1509 secondary_contrib += in_ambient[component] * in_lightAmbientColor[posNum];
1515 for(int dirNum = NUMBER_POS_LIGHTS; dirNum < TOTAL_NUMBER_LIGHTS; dirNum++)
1517 tex_light = g_lightDirectionTex[dirNum];
1518 phase = phase_function(dot(normalize(-tex_light), view_tdir));
1519 vol_shadow = volumeShadow(g_dataPos, tex_light, 0.0, component, in_volume[0], 0, label);
1520 secondary_contrib += vol_shadow * phase * color.rgb * in_diffuse[component] * in_lightDiffuseColor[dirNum];
1521 secondary_contrib += in_ambient[component] * in_lightAmbientColor[dirNum];
1526 shaderStr += blendingFormula +
1528 finalColor.xyz = (1.0 - vol_coef) * finalColor.xyz + vol_coef * secondary_contrib;
1538 if (noOfComponents == 1 || !independentComponents)
1543 \n if (gradient.w >= 0.0 && label == 0.0)\
1545 \n color.a *= computeGradientOpacity(gradient);\
1551 \n if (gradient.w >= 0.0 && label > 0.0)\
1553 \n color.a *= computeGradientOpacityForLabel(gradient, label);\
1557 else if (noOfComponents > 1 && independentComponents && volProperty->
HasGradientOpacity())
1560 \n if (gradient.w >= 0.0)\
1562 \n for (int i = 0; i < in_noOfComponents; ++i)\
1564 \n color.a = color.a *\
1565 \n computeGradientOpacity(gradient, i) * in_componentWeight[i];\
1572 \n finalColor.a = color.a;\
1573 \n return finalColor;\
1581 vtkVolume* vol,
int noOfComponents,
int independentComponents,
1582 int vtkNotUsed(totalNumberOfLights),
bool defaultLighting)
1592 \nvec4 computeLighting(vec3 texPos, vec4 color, const in sampler2D gradientTF, const in sampler3D volume, const in sampler2D opacityTF, const int volIdx, int component)\
1594 \n vec4 finalColor = vec4(0.0);\n");
1599 \nvec4 computeLighting(vec3 texPos, vec4 color, const in sampler3D volume, const in sampler2D opacityTF, const int volIdx, int component)\
1601 \n vec4 finalColor = vec4(0.0);\n");
1605 int const shadeReqd = volProperty->
GetShade() &&
1619 if (glMapper->GetComputeNormalFromOpacity())
1623 shaderStr +=
" vec4 shading_gradient = computeDensityGradient(texPos, component, volume, "
1624 "opacityTF, gradientTF, volIdx, 0.0);\n";
1628 shaderStr +=
" vec4 shading_gradient = computeDensityGradient(texPos, component, volume, "
1629 "opacityTF, volIdx, 0.0);\n";
1635 " vec4 shading_gradient = computeGradient(texPos, component, volume, volIdx);\n";
1642 if (!shadeReqd || glMapper->GetComputeNormalFromOpacity())
1644 shaderStr +=
" vec4 gradient = computeGradient(texPos, component, volume, volIdx);\n";
1649 shaderStr +=
" vec4 gradient = shading_gradient;\n";
1653 if (shadeReqd && defaultLighting)
1656 \n vec3 diffuse = vec3(0.0);\
1657 \n vec3 specular = vec3(0.0);\
1658 \n vec3 normal = shading_gradient.xyz;\
1659 \n float normalLength = length(normal);\
1660 \n if (normalLength > 0.0)\
1662 \n normal = normalize(normal);\
1666 \n normal = vec3(0.0, 0.0, 0.0);\
1668 \n // normal is oriented inside the volume (because normal = gradient, oriented inside the volume)\
1669 \n // thus we have to take minus everything\
1670 \n float nDotL = dot(normal, -g_ldir[volIdx]);\
1671 \n vec3 r = normalize(2.0 * nDotL * normal + g_ldir[volIdx]);\
1672 \n float vDotR = dot(r, -g_vdir[volIdx]);\
1673 \n if (nDotL < 0.0 && in_twoSidedLighting)\
1677 \n if (nDotL > 0.0)\
1679 \n diffuse = nDotL * in_diffuse[component] *\
1680 \n in_lightDiffuseColor[0] * color.rgb;\
1681 \n vDotR = max(vDotR, 0.0);\
1682 \n specular = pow(vDotR, in_shininess[component]) *\
1683 \n in_specular[component] *\
1684 \n in_lightSpecularColor[0];\
1686 \n finalColor.xyz = in_ambient[component] * color.rgb * in_lightAmbientColor[0] +\
1687 \n diffuse + specular;\
1692 shaderStr +=
std::string(
"\n finalColor = vec4(color.rgb, 0.0);");
1699 if (volProperty->
HasGradientOpacity() && (noOfComponents == 1 || !independentComponents))
1702 \n if (gradient.w >= 0.0)\
1704 \n color.a = color.a *\
1705 \n computeGradientOpacity(gradient, gradientTF);\
1711 \n finalColor.a = color.a;\
1712 \n return clamp(finalColor, 0.0, 1.0);\
1720 vtkVolume* vtkNotUsed(vol),
int vtkNotUsed(noOfComponents))
1725 \nvec3 computeRayDirection()\
1727 \n return normalize(ip_vertexPos.xyz - g_eyePosObj.xyz);\
1733 \nuniform vec3 in_projectionDirection;\
1734 \nvec3 computeRayDirection()\
1736 \n return normalize((in_inverseVolumeMatrix[0] *\
1737 \n vec4(in_projectionDirection, 0.0)).xyz);\
1747 if (inputs.size() > 1)
1750 for (
auto& item : inputs)
1752 const auto& prop = item.second.Volume->GetProperty();
1756 auto& map = item.second.RGBTablesMap;
1757 const auto numComp = map.size();
1759 "uniform sampler2D " + ArrayBaseName(map[0]) +
"[" + std::to_string(numComp) +
"];\n";
1767 resStr +=
"uniform sampler2D " + ArrayBaseName(inputs[0].RGBTablesMap[0]) +
"[" +
1768 std::to_string(noOfComponents) +
"];\n";
1778 int independentComponents, std::map<int, std::string> colorTableMap)
1780 std::ostringstream ss;
1783 if (noOfComponents == 1)
1786 \nvec4 computeColor(vec4 scalar, float opacity)\
1788 \n return clamp(computeLighting(vec4(texture2D(" +
1789 colorTableMap[0] +
",\
1790 \n vec2(scalar.w, 0.0)).xyz, opacity), 0, 0.0), 0.0, 1.0);\
1794 else if (noOfComponents > 1 && independentComponents)
1796 std::ostringstream toString;
1799 \nvec4 computeColor(vec4 scalar, float opacity, int component)\
1802 for (
int i = 0; i < noOfComponents; ++i)
1806 \n if (component == " +
1807 toString.str() +
")");
1811 \n return clamp(computeLighting(vec4(texture2D(\
1816 toString.str() +
"],0.0)).xyz,\
1818 toString.str() +
", 0.0), 0.0, 1.0);\
1829 else if (noOfComponents == 2 && !independentComponents)
1832 \nvec4 computeColor(vec4 scalar, float opacity)\
1834 \n return clamp(computeLighting(vec4(texture2D(" +
1835 colorTableMap[0] +
",\
1836 \n vec2(scalar.x, 0.0)).xyz,\
1837 \n opacity), 0, 0.0), 0.0, 1.0);\
1844 \nvec4 computeColor(vec4 scalar, float opacity)\
1846 \n return clamp(computeLighting(vec4(scalar.xyz, opacity), 0, 0.0), 0.0, 1.0);\
1856 std::ostringstream ss;
1858 std::map<int, std::string> lastColorTableMap;
1859 for (
auto& item : inputs)
1861 auto prop = item.second.Volume->GetProperty();
1864 auto& map = item.second.RGBTablesMap;
1865 lastComponentMode = item.second.ComponentMode;
1866 lastColorTableMap = map;
1871 ss <<
"vec4 computeColor(vec4 scalar, const in sampler2D colorTF)\
1873 \n return clamp(computeLighting(vec4(texture2D(colorTF,\
1874 \n vec2(scalar.w, 0.0)).xyz, opacity), 0), 0.0, 1.0);\
1882 <<
"vec4 computeColor(vec3 texPos, vec4 scalar, float opacity, const in sampler2D colorTF, "
1883 "const in sampler2D gradientTF, const in sampler3D volume, const in sampler2D "
1884 "opacityTF, const int volIdx)\n\n"
1886 " return clamp(computeLighting(texPos, vec4(texture2D(colorTF,\n"
1887 " vec2(scalar.w, 0.0)).xyz, opacity), gradientTF, volume, "
1889 "volIdx, 0), 0.0, 1.0);\n"
1895 <<
"vec4 computeColor(vec3 texPos, vec4 scalar, float opacity, const in sampler2D colorTF, "
1896 "const in sampler3D volume, const in sampler2D opacityTF, const int volIdx)\n\n"
1898 " return clamp(computeLighting(texPos, vec4(texture2D(colorTF,\n"
1899 " vec2(scalar.w, 0.0)).xyz, opacity), volume, opacityTF,"
1900 "volIdx, 0), 0.0, 1.0);\n"
1911 std::ostringstream ss;
1913 for (
auto& item : inputs)
1915 auto prop = item.second.Volume->GetProperty();
1919 auto& map = item.second.OpacityTablesMap;
1920 const auto numComp = map.size();
1921 ss <<
"uniform sampler2D " << ArrayBaseName(map[0]) <<
"[" << numComp <<
"];\n";
1925 ss <<
"float computeOpacity(vec4 scalar, const in sampler2D opacityTF)\n"
1927 " return texture2D(opacityTF, vec2(scalar.w, 0)).r;\n"
1936 std::ostringstream ss;
1939 for (
auto& item : inputs)
1941 auto prop = item.second.Volume->GetProperty();
1945 auto& map = item.second.GradientOpacityTablesMap;
1946 const auto numComp = map.size();
1947 ss <<
"uniform sampler2D " << ArrayBaseName(map[0]) <<
"[" << numComp <<
"];\n";
1951 ss <<
"float computeGradientOpacity(vec4 grad, const in sampler2D gradientTF)\n"
1953 " return texture2D(gradientTF, vec2(grad.w, 0.0)).r;\n"
1961 int independentComponents, std::map<int, std::string> opacityTableMap)
1963 std::ostringstream ss;
1964 ss <<
"uniform sampler2D " << ArrayBaseName(opacityTableMap[0]) <<
"[" << noOfComponents
1968 if (noOfComponents > 1 && independentComponents)
1971 \nfloat computeOpacity(vec4 scalar, int component)\
1974 for (
int i = 0; i < noOfComponents; ++i)
1976 std::ostringstream toString;
1979 \n if (component == " +
1980 toString.str() +
")");
1984 \n return texture2D(" +
1985 opacityTableMap[i]);
1987 shaderStr +=
std::string(
",vec2(scalar[" + toString.str() +
"], 0)).r;\
1994 else if (noOfComponents == 2 && !independentComponents)
1997 \nfloat computeOpacity(vec4 scalar)\
1999 \n return texture2D(" +
2000 opacityTableMap[0] +
", vec2(scalar.y, 0)).r;\
2007 \nfloat computeOpacity(vec4 scalar)\
2009 \n return texture2D(" +
2010 opacityTableMap[0] +
", vec2(scalar.w, 0)).r;\
2018 int vtkNotUsed(independentComponents), std::map<int, std::string> colorTableMap)
2020 if (noOfComponents == 1)
2024 "vec4 computeColor(vec4 scalar, float opacity)\n"
2026 " vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
2027 " yscalar.r = yscalar.r * in_transfer2DYAxis_scale.r + in_transfer2DYAxis_bias.r;\n"
2028 " yscalar = vec4(yscalar.r);\n"
2029 " vec4 color = texture2D(" +
2032 " vec2(scalar.w, yscalar.w));\n"
2033 " return computeLighting(color, 0, 0);\n"
2036 return std::string(
"vec4 computeColor(vec4 scalar, float opacity)\n"
2038 " return vec4(0, 0, 0, 0)\n"
2045 int independentComponents, std::map<int, std::string> colorTableMap,
int useGradient)
2051 if (noOfComponents == 1)
2054 return std::string(
"vec4 computeColor(vec4 scalar, float opacity)\n"
2056 " vec4 color = texture2D(" +
2059 " vec2(scalar.w, g_gradients_0[0].w));\n"
2060 " return computeLighting(color, 0, 0);\n"
2063 else if (noOfComponents > 1 && independentComponents)
2067 shaderStr +=
std::string(
"vec4 computeColor(vec4 scalar, float opacity, int component)\n"
2070 for (
int i = 0; i < noOfComponents; ++i)
2072 std::ostringstream toString;
2075 shaderStr +=
std::string(
" if (component == " + num +
2078 " vec4 color = texture2D(" +
2082 num +
"], g_gradients_0[" + num +
2084 " return computeLighting(color, " +
2093 else if (noOfComponents == 2 && !independentComponents)
2096 return std::string(
"vec4 computeColor(vec4 scalar, float opacity)\n"
2098 " vec4 color = texture2D(" +
2101 " vec2(scalar.x, g_gradients_0[0].w));\n"
2102 " return computeLighting(color, 0, 0.0);\n"
2107 return std::string(
"vec4 computeColor(vec4 scalar, float opacity)\n"
2109 " return computeLighting(vec4(scalar.xyz, opacity), 0, 0.0);\n"
2117 std::ostringstream ss;
2119 for (
auto& item : inputs)
2121 auto prop = item.second.Volume->GetProperty();
2125 auto& map = item.second.TransferFunctions2DMap;
2126 const auto numComp = map.size();
2127 ss <<
"uniform sampler2D " << ArrayBaseName(map[0]) <<
"[" << numComp <<
"];\n";
2132 std::string(
"uniform sampler3D in_transfer2DYAxis;\n"
2133 "uniform vec4 in_transfer2DYAxis_scale;\n"
2134 "uniform vec4 in_transfer2DYAxis_bias;\n");
2142 int independentComponents, std::map<int, std::string> opacityTableMap,
int useGradient)
2144 std::ostringstream toString;
2145 if (noOfComponents > 1 && independentComponents)
2148 toString <<
"float computeOpacity(vec4 scalar, int component)\n"
2153 <<
"vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
2154 "for (int i = 0; i < 4; ++i)\n"
2156 " yscalar[i] = yscalar[i] * in_transfer2DYAxis_scale[i] + in_transfer2DYAxis_bias[i];\n"
2158 if (noOfComponents == 1)
2160 toString <<
"yscalar = vec4(yscalar.r);\n";
2164 for (
int i = 0; i < noOfComponents; ++i)
2168 toString <<
" if (component == " << i
2171 " return texture2D("
2172 << opacityTableMap[i]
2175 << i <<
"], g_gradients_0[" << i
2181 toString <<
" if (component == " << i
2184 " return texture2D("
2185 << opacityTableMap[i]
2188 << i <<
"], yscalar[" << i
2197 else if (noOfComponents == 2 && !independentComponents)
2202 toString <<
"float computeOpacity(vec4 scalar)\n"
2204 " return texture2D(" +
2205 opacityTableMap[0] +
2207 " vec2(scalar.y, g_gradients_0[0].w)).a;\n"
2213 toString <<
"float computeOpacity(vec4 scalar)\n"
2215 " return texture2D(" +
2216 opacityTableMap[0] +
2218 " vec2(scalar.y, yscalar.y)).a;\n"
2228 toString <<
"float computeOpacity(vec4 scalar)\n"
2230 " return texture2D(" +
2231 opacityTableMap[0] +
2233 " vec2(scalar.a, g_gradients_0[0].w)).a;\n"
2240 <<
"float computeOpacity(vec4 scalar)\n"
2242 " vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
2243 " yscalar.r = yscalar.r * in_transfer2DYAxis_scale.r + in_transfer2DYAxis_bias.r;\n"
2244 " yscalar = vec4(yscalar.r);\n"
2245 " return texture2D(" +
2246 opacityTableMap[0] +
2248 " vec2(scalar.a, yscalar.w)).a;\n"
2252 return toString.str();
2257 vtkVolume* vtkNotUsed(vol),
int noOfComponents,
int independentComponents,
2266 const size_t numInputs = inputs.size();
2267 const bool hasGradOp = ::HasGradientOpacity(inputs);
2272 functionSignature =
"float volumeShadow(vec3 sample_position, vec3 light_pos_dir, float is_Pos, "
2273 " in int c, in sampler3D volume, " +
2275 (numInputs > 1 && hasGradOp ? std::string(
"in sampler2D gradTF, ") :
std::string()) +
2276 "int index, float label)\n";
2281 vec3 direction = vec3(0.0);
2282 vec3 norm_dir = vec3(0.0);
2283 float maxdist = 0.0;
2286 float opacity = 0.0;
2290 float sampled_dist = 0.0;
2291 vec3 sampled_point = vec3(0.0);
2296 // direction is light_pos_dir when light is directional
2297 // and light_pos_dir - sample_position when positional
2298 direction = light_pos_dir - is_Pos * sample_position;
2299 norm_dir = normalize(direction);
2300 // introduce little offset to avoid sampling shadows at the exact
2302 sample_position += g_lengthStep * norm_dir;
2303 direction = light_pos_dir - is_Pos * sample_position;
2304 ray.origin = sample_position;
2307 ray.invDir = 1.0/ray.dir;
2308 if(!BBoxIntersect(vec3(0.0), vec3(1.0), ray, hit))
2310 // it can happen around the bounding box
2313 if(hit.tmax < g_lengthStep)
2315 // if we're too close to the bounding box
2318 // in case of directional light, we want direction not to be normalized but to go
2319 // all the way to the bbox
2320 direction *= pow(hit.tmax / length(direction), 1.0 - is_Pos);
2321 maxdist = min(hit.tmax, length(direction));
2322 maxdist = min(in_giReach, maxdist);
2323 if(maxdist < EPSILON) return 1.0;
2329 opacityEval +=
" scalar = texture3D(volume, sampled_point)[c];\n"
2330 " scalar = scalar * in_volume_scale[index][c] + in_volume_bias[index][c];\n";
2332 mapper, inputs, noOfComponents, independentComponents, useGradYAxis,
"sampled_point",
true);
2334 resStr += functionSignature +
"{\n" + declarations + rayInit +
2336 float current_dist = 0.0;
2337 float current_step = g_lengthStep;
2338 float clamped_step = 0.0;
2339 while(current_dist < maxdist)
2341 clamped_step = min(maxdist - current_dist, current_step);
2342 sampled_dist = current_dist + clamped_step * g_jitterValue;
2343 sampled_point = sample_position + sampled_dist * norm_dir;
2347 shadow *= 1.0 - opacity;
2348 current_dist += current_step;
2371 \n bool l_firstValue;\
2372 \n vec4 l_maxValue;");
2377 \n bool l_firstValue;\
2378 \n vec4 l_minValue;");
2383 \n uvec4 l_numSamples;\
2384 \n vec4 l_avgValue;");
2389 \n vec4 l_sumValue;");
2394 \n int l_initialIndex = 0;\
2395 \n float l_normValues[NUMBER_OF_CONTOURS + 2];");
2410 \n // We get data between 0.0 - 1.0 range\
2411 \n l_firstValue = true;\
2412 \n l_maxValue = vec4(0.0);");
2417 \n //We get data between 0.0 - 1.0 range\
2418 \n l_firstValue = true;\
2419 \n l_minValue = vec4(1.0);");
2424 \n //We get data between 0.0 - 1.0 range\
2425 \n l_avgValue = vec4(0.0);\
2426 \n // Keep track of number of samples\
2427 \n l_numSamples = uvec4(0);");
2432 \n //We get data between 0.0 - 1.0 range\
2433 \n l_sumValue = vec4(0.0);");
2438 \n#if NUMBER_OF_CONTOURS\
2439 \n l_normValues[0] = -1e20; //-infinity\
2440 \n l_normValues[NUMBER_OF_CONTOURS+1] = +1e20; //+infinity\
2441 \n for (int i = 0; i < NUMBER_OF_CONTOURS; i++)\
2443 \n l_normValues[i+1] = (in_isosurfacesValues[i] - in_scalarsRange[0].x) / \
2444 \n (in_scalarsRange[0].y - in_scalarsRange[0].x);\
2459 const int numInputs =
static_cast<int>(inputs.size());
2460 const int comp = numInputs == 1 ?
2462 (!independentComponents ? 1 : numInputs)
2467 std::ostringstream toShader;
2468 for (
const auto& item : inputs)
2470 auto& input = item.second;
2471 if (input.Volume->GetProperty()->HasGradientOpacity())
2473 toShader <<
"vec4 " << input.GradientCacheName <<
"[" << comp <<
"];\n";
2477 return toShader.str();
2482 int noOfComponents = 1,
int independentComponents = 0)
2484 std::ostringstream shader;
2485 if (independentComponents)
2487 if (noOfComponents == 1)
2489 shader <<
"g_gradients_0[0] = computeGradient(g_dataPos, 0, in_volume[0], 0);\n";
2494 shader <<
"for (int comp = 0; comp < in_noOfComponents; comp++)\n"
2496 " g_gradients_0[comp] = computeGradient(g_dataPos, comp, in_volume[0], 0);\n"
2502 shader <<
"g_gradients_0[0] = computeGradient(g_dataPos, 0, in_volume[0], 0);\n";
2505 return shader.str();
2512 std::ostringstream toShaderStr;
2513 toShaderStr <<
" if (!g_skip)\n"
2523 for (
auto& item : inputs)
2525 auto& input = item.second;
2526 auto property = input.Volume->GetProperty();
2528 const auto idx = i + 1;
2533 " texPos = (in_cellToPoint[" << idx <<
"] * in_inverseTextureDatasetMatrix[" << idx
2534 <<
"] * in_inverseVolumeMatrix[" << idx
2536 " in_volumeMatrix[0] * in_textureDatasetMatrix[0] * "
2537 "vec4(g_dataPos.xyz, 1.0)).xyz;\n"
2538 " if ((all(lessThanEqual(texPos, vec3(1.0))) &&\n"
2539 " all(greaterThanEqual(texPos, vec3(0.0)))))\n"
2541 " vec4 scalar = texture3D(in_volume["
2544 " scalar = scalar * in_volume_scale["
2545 << i <<
"] + in_volume_bias[" << i
2547 " scalar = vec4(scalar.r);\n"
2548 " g_srcColor = vec4(0.0);\n";
2552 std::string gradientopacity_param = (
property->HasGradientOpacity())
2553 ? input.GradientOpacityTablesMap[0] +
std::string(
", ")
2556 toShaderStr <<
" g_srcColor.a = computeOpacity(scalar,"
2557 << input.OpacityTablesMap[0]
2559 " if (g_srcColor.a > 0.0)\n"
2561 " g_srcColor = computeColor(texPos, scalar, g_srcColor.a, "
2562 << input.RGBTablesMap[0] <<
", " << gradientopacity_param <<
"in_volume[" << i
2563 <<
"], " << input.OpacityTablesMap[0] <<
", " << i <<
");\n";
2565 if (property->HasGradientOpacity())
2567 const auto& grad = input.GradientCacheName;
2568 toShaderStr <<
" " << grad <<
"[0] = computeGradient(texPos, 0, "
2569 <<
"in_volume[" << i <<
"], " << i
2573 <<
"[0].w >= 0.0)\n"
2575 " g_srcColor.a *= computeGradientOpacity("
2576 << grad <<
"[0], " << input.GradientOpacityTablesMap[0]
2583 const auto& grad = input.GradientCacheName;
2586 " " << grad <<
"[0] = computeGradient(texPos, 0, "
2587 <<
"in_volume[" << i <<
"], " << i
2589 " g_srcColor = texture2D("
2590 << input.TransferFunctions2DMap[0] <<
", vec2(scalar.r, "
2591 << input.GradientCacheName
2593 " if (g_srcColor.a > 0.0)\n"
2598 <<
" g_srcColor.rgb *= g_srcColor.a;\n"
2599 " g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;\n"
2608 toShaderStr <<
" }\n";
2610 return toShaderStr.str();
2616 int noOfComponents,
int independentComponents = 0)
2630 \n // Compute IJK vertex position for current sample in the rectilinear grid\
2631 \n vec4 dataPosWorld = in_volumeMatrix[0] * in_textureDatasetMatrix[0] * vec4(g_dataPos, 1.0);\
2632 \n dataPosWorld = dataPosWorld / dataPosWorld.w;\
2633 \n dataPosWorld.w = 1.0;\
2634 \n ivec3 ijk = ivec3(0);\
2635 \n vec3 ijkTexCoord = vec3(0.0);\
2636 \n vec3 pCoords = vec3(0.0);\
2637 \n vec3 xPrev, xNext, tmp;\
2638 \n int sz = textureSize(in_coordTexs, 0);\
2639 \n vec4 dataPosWorldScaled = dataPosWorld * vec4(in_coordsScale, 1.0) +\
2640 \n vec4(in_coordsBias, 1.0);\
2641 \n for (int j = 0; j < 3; ++j)\
2643 \n xPrev = texture1D(in_coordTexs, 0.0).xyz;\
2644 \n xNext = texture1D(in_coordTexs, (in_coordTexSizes[j] - 1) / sz).xyz;\
2645 \n if (xNext[j] < xPrev[j])\
2651 \n for (int i = 0; i < int(in_coordTexSizes[j]); i++)\
2653 \n xNext = texture1D(in_coordTexs, (i + 0.5) / sz).xyz;\
2654 \n if (dataPosWorldScaled[j] >= xPrev[j] && dataPosWorldScaled[j] < xNext[j])\
2657 \n pCoords[j] = (dataPosWorldScaled[j] - xPrev[j]) / (xNext[j] - xPrev[j]);\
2660 \n else if (dataPosWorldScaled[j] == xNext[j])\
2663 \n pCoords[j] = 1.0;\
2668 \n ijkTexCoord[j] = (ijk[j] + pCoords[j]) / in_coordTexSizes[j];\
2670 \n scalar = texture3D(in_volume[0], sign(in_cellSpacing[0]) * ijkTexCoord);\
2676 \n scalar = texture3D(in_volume[0], g_dataPos);\
2681 if (noOfComponents == 1)
2684 \n scalar.r = scalar.r * in_volume_scale[0].r + in_volume_bias[0].r;\
2685 \n scalar = vec4(scalar.r);");
2691 \n scalar = scalar * in_volume_scale[0] + in_volume_bias[0];");
2696 if (noOfComponents > 1)
2698 if (!independentComponents)
2701 \n if (l_maxValue.w < scalar.w || l_firstValue)\
2703 \n l_maxValue = scalar;\
2706 \n if (l_firstValue)\
2708 \n l_firstValue = false;\
2714 \n for (int i = 0; i < in_noOfComponents; ++i)\
2716 \n if (l_maxValue[i] < scalar[i] || l_firstValue)\
2718 \n l_maxValue[i] = scalar[i];\
2721 \n if (l_firstValue)\
2723 \n l_firstValue = false;\
2730 \n if (l_maxValue.w < scalar.x || l_firstValue)\
2732 \n l_maxValue.w = scalar.x;\
2735 \n if (l_firstValue)\
2737 \n l_firstValue = false;\
2743 if (noOfComponents > 1)
2745 if (!independentComponents)
2748 \n if (l_minValue.w > scalar.w || l_firstValue)\
2750 \n l_minValue = scalar;\
2753 \n if (l_firstValue)\
2755 \n l_firstValue = false;\
2761 \n for (int i = 0; i < in_noOfComponents; ++i)\
2763 \n if (l_minValue[i] < scalar[i] || l_firstValue)\
2765 \n l_minValue[i] = scalar[i];\
2768 \n if (l_firstValue)\
2770 \n l_firstValue = false;\
2777 \n if (l_minValue.w > scalar.x || l_firstValue)\
2779 \n l_minValue.w = scalar.x;\
2782 \n if (l_firstValue)\
2784 \n l_firstValue = false;\
2790 if (noOfComponents > 1 && independentComponents)
2793 \n for (int i = 0; i < in_noOfComponents; ++i)\
2795 \n // Get the intensity in volume scalar range\
2796 \n float intensity = in_scalarsRange[i][0] +\
2797 \n (in_scalarsRange[i][1] -\
2798 \n in_scalarsRange[i][0]) * scalar[i];\
2799 \n if (in_averageIPRange.x <= intensity &&\
2800 \n intensity <= in_averageIPRange.y)\
2802 \n l_avgValue[i] += computeOpacity(scalar, i) * scalar[i];\
2803 \n ++l_numSamples[i];\
2810 \n // Get the intensity in volume scalar range\
2811 \n float intensity = in_scalarsRange[0][0] +\
2812 \n (in_scalarsRange[0][1] -\
2813 \n in_scalarsRange[0][0]) * scalar.x;\
2814 \n if (in_averageIPRange.x <= intensity &&\
2815 \n intensity <= in_averageIPRange.y)\
2817 \n l_avgValue.x += computeOpacity(scalar) * scalar.x;\
2818 \n ++l_numSamples.x;\
2824 if (noOfComponents > 1 && independentComponents)
2827 \n for (int i = 0; i < in_noOfComponents; ++i)\
2829 \n float opacity = computeOpacity(scalar, i);\
2830 \n l_sumValue[i] = l_sumValue[i] + opacity * scalar[i];\
2836 \n float opacity = computeOpacity(scalar);\
2837 \n l_sumValue.x = l_sumValue.x + opacity * scalar.x;");
2843 \n#if NUMBER_OF_CONTOURS\
2844 \n int maxComp = 0;");
2847 if (noOfComponents > 1 && independentComponents)
2850 \n for (int i = 1; i < in_noOfComponents; ++i)\
2852 \n if (in_componentWeight[i] > in_componentWeight[maxComp])\
2855 compParamStr =
", maxComp";
2858 \n if (g_currentT == 0)\
2860 \n l_initialIndex = findIsoSurfaceIndex(scalar[maxComp], l_normValues);\
2865 \n bool shade = false;\
2866 \n l_initialIndex = clamp(l_initialIndex, 0, NUMBER_OF_CONTOURS);\
2867 \n if (scalar[maxComp] < l_normValues[l_initialIndex])\
2869 \n s = l_normValues[l_initialIndex];\
2870 \n l_initialIndex--;\
2873 \n if (scalar[maxComp] > l_normValues[l_initialIndex+1])\
2875 \n s = l_normValues[l_initialIndex+1];\
2876 \n l_initialIndex++;\
2879 \n if (shade == true)\
2881 \n vec4 vs = vec4(s);\
2882 \n g_srcColor.a = computeOpacity(vs " +
2884 \n g_srcColor = computeColor(vs, g_srcColor.a " +
2886 \n g_srcColor.rgb *= g_srcColor.a;\
2887 \n g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;\
2895 \n // test if the intersection is inside the volume bounds\
2896 \n if (any(greaterThan(g_dataPos, vec3(1.0))) || any(lessThan(g_dataPos, vec3(0.0))))\
2900 \n float opacity = computeOpacity(scalar);\
2901 \n g_fragColor = computeColor(scalar, opacity);\
2902 \n g_fragColor.rgb *= opacity;\
2903 \n g_exit = true;");
2907 if (noOfComponents > 1 && independentComponents)
2910 \n vec4 color[4]; vec4 tmp = vec4(0.0);\
2911 \n float totalAlpha = 0.0;\
2912 \n for (int i = 0; i < in_noOfComponents; ++i)\
2915 if (glMapper->GetUseDepthPass() &&
2919 \n // Data fetching from the red channel of volume texture\
2920 \n float opacity = computeOpacity(scalar, i);\
2921 \n if (opacity > 0.0)\
2923 \n g_srcColor.a = opacity;\
2930 \n // Data fetching from the red channel of volume texture\
2931 \n color[i][3] = computeOpacity(scalar, i);\
2932 \n color[i] = computeColor(scalar, color[i][3], i);\
2933 \n totalAlpha += color[i][3] * in_componentWeight[i];\
2935 \n if (totalAlpha > 0.0)\
2937 \n for (int i = 0; i < in_noOfComponents; ++i)\
2939 \n // Only let visible components contribute to the final color\
2940 \n if (in_componentWeight[i] <= 0) continue;\
2942 \n tmp.x += color[i].x * color[i].w * in_componentWeight[i];\
2943 \n tmp.y += color[i].y * color[i].w * in_componentWeight[i];\
2944 \n tmp.z += color[i].z * color[i].w * in_componentWeight[i];\
2945 \n tmp.w += ((color[i].w * color[i].w)/totalAlpha);\
2948 \n g_fragColor = (1.0f - g_fragColor.a) * tmp + g_fragColor;");
2951 else if (glMapper->GetUseDepthPass() &&
2955 \n g_srcColor = vec4(0.0);\
2956 \n g_srcColor.a = computeOpacity(scalar);");
2963 \n g_srcColor = vec4(0.0);\
2964 \n g_srcColor.a = computeOpacity(scalar);\
2965 \n if (g_srcColor.a > 0.0)\
2967 \n g_srcColor = computeColor(scalar, g_srcColor.a);");
2971 \n // Opacity calculation using compositing:\
2972 \n // Here we use front to back compositing scheme whereby\
2973 \n // the current sample value is multiplied to the\
2974 \n // currently accumulated alpha and then this product\
2975 \n // is subtracted from the sample value to get the\
2976 \n // alpha from the previous steps. Next, this alpha is\
2977 \n // multiplied with the current sample colour\
2978 \n // and accumulated to the composited colour. The alpha\
2979 \n // value from the previous steps is then accumulated\
2980 \n // to the composited colour alpha.\
2981 \n g_srcColor.rgb *= g_srcColor.a;\
2982 \n g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;");
3006 \n // Special coloring mode which renders the Prop Id in fragments that\
3007 \n // have accumulated certain level of opacity. Used during the selection\
3008 \n // pass vtkHardwareSelection::ACTOR_PASS.\
3009 \n if (g_fragColor.a > 3.0/ 255.0)\
3011 \n gl_FragData[0] = vec4(in_propId, 1.0);\
3015 \n gl_FragData[0] = vec4(0.0);\
3025 \n // Special coloring mode which renders the voxel index in fragments that\
3026 \n // have accumulated certain level of opacity. Used during the selection\
3027 \n // pass vtkHardwareSelection::ID_LOW24.\
3028 \n if (g_fragColor.a > 3.0/ 255.0)\
3030 \n uvec3 volumeDim = uvec3(in_textureExtentsMax - in_textureExtentsMin);\
3031 \n uvec3 voxelCoords = uvec3(volumeDim * g_dataPos);\
3032 \n // vtkHardwareSelector assumes index 0 to be empty space, so add uint(1).\
3033 \n uint idx = volumeDim.x * volumeDim.y * voxelCoords.z +\
3034 \n volumeDim.x * voxelCoords.y + voxelCoords.x + uint(1);\
3035 \n gl_FragData[0] = vec4(float(idx % uint(256)) / 255.0,\
3036 \n float((idx / uint(256)) % uint(256)) / 255.0,\
3037 \n float((idx / uint(65536)) % uint(256)) / 255.0, 1.0);\
3041 \n gl_FragData[0] = vec4(0.0);\
3051 \n // Special coloring mode which renders the voxel index in fragments that\
3052 \n // have accumulated certain level of opacity. Used during the selection\
3053 \n // pass vtkHardwareSelection::ID_MID24.\
3054 \n if (g_fragColor.a > 3.0/ 255.0)\
3056 \n uvec3 volumeDim = uvec3(in_textureExtentsMax - in_textureExtentsMin);\
3057 \n uvec3 voxelCoords = uvec3(volumeDim * g_dataPos);\
3058 \n // vtkHardwareSelector assumes index 0 to be empty space, so add uint(1).\
3059 \n uint idx = volumeDim.x * volumeDim.y * voxelCoords.z +\
3060 \n volumeDim.x * voxelCoords.y + voxelCoords.x + uint(1);\
3061 \n idx = ((idx & 0xff000000) >> 24);\
3062 \n gl_FragData[0] = vec4(float(idx % uint(256)) / 255.0,\
3063 \n float((idx / uint(256)) % uint(256)) / 255.0,\
3064 \n float(idx / uint(65536)) / 255.0, 1.0);\
3068 \n gl_FragData[0] = vec4(0.0);\
3075 vtkVolume* vtkNotUsed(vol),
int noOfComponents,
int independentComponents = 0)
3087 if (noOfComponents > 1 && independentComponents)
3090 \n g_srcColor = vec4(0);\
3091 \n for (int i = 0; i < in_noOfComponents; ++i)\
3093 \n vec4 tmp = computeColor(l_maxValue, computeOpacity(l_maxValue, i), i);\
3094 \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
3095 \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
3096 \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
3097 \n g_srcColor[3] += tmp[3] * in_componentWeight[i];\
3099 \n g_fragColor = g_srcColor;");
3104 \n g_srcColor = computeColor(l_maxValue,\
3105 \n computeOpacity(l_maxValue));\
3106 \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
3107 \n g_fragColor.a = g_srcColor.a;");
3112 if (noOfComponents > 1 && independentComponents)
3115 \n g_srcColor = vec4(0);\
3116 \n for (int i = 0; i < in_noOfComponents; ++i)\
3118 \n vec4 tmp = computeColor(l_minValue, computeOpacity(l_minValue, i), i);\
3119 \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
3120 \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
3121 \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
3122 \n g_srcColor[2] += tmp[3] * tmp[3] * in_componentWeight[i];\
3124 \n g_fragColor = g_srcColor;");
3129 \n g_srcColor = computeColor(l_minValue,\
3130 \n computeOpacity(l_minValue));\
3131 \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
3132 \n g_fragColor.a = g_srcColor.a;");
3137 if (noOfComponents > 1 && independentComponents)
3140 \n for (int i = 0; i < in_noOfComponents; ++i)\
3142 \n if (l_numSamples[i] == uint(0))\
3146 \n l_avgValue[i] = l_avgValue[i] * in_componentWeight[i] /\
3147 \n l_numSamples[i];\
3150 \n l_avgValue[0] += l_avgValue[i];\
3153 \n l_avgValue[0] = clamp(l_avgValue[0], 0.0, 1.0);\
3154 \n g_fragColor = vec4(vec3(l_avgValue[0]), 1.0);");
3159 \n if (l_numSamples.x == uint(0))\
3165 \n l_avgValue.x /= l_numSamples.x;\
3166 \n l_avgValue.x = clamp(l_avgValue.x, 0.0, 1.0);\
3167 \n g_fragColor = vec4(vec3(l_avgValue.x), 1.0);\
3173 if (noOfComponents > 1 && independentComponents)
3177 \n l_sumValue.x *= in_componentWeight.x;\
3178 \n for (int i = 1; i < in_noOfComponents; ++i)\
3180 \n l_sumValue.x += l_sumValue[i] * in_componentWeight[i];\
3182 \n l_sumValue.x = clamp(l_sumValue.x, 0.0, 1.0);\
3183 \n g_fragColor = vec4(vec3(l_sumValue.x), 1.0);");
3188 \n l_sumValue.x = clamp(l_sumValue.x, 0.0, 1.0);\
3189 \n g_fragColor = vec4(vec3(l_sumValue.x), 1.0);");
3210 \n const float g_opacityThreshold = 1.0 - 1.0 / 255.0;");
3218 \n uniform vec3 in_propId;");
3226 \n // Flag to indicate if the raymarch loop should terminate \
3227 \n bool stop = false;\
3229 \n g_terminatePointMax = 0.0;\
3231 \n vec4 l_depthValue = texture2D(in_depthSampler, fragTexCoord);\
3233 \n if(gl_FragCoord.z >= l_depthValue.x)\
3238 \n // color buffer or max scalar buffer have a reduced size.\
3239 \n fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
3240 \n in_inverseOriginalWindowSize;\
3248 if (sliceFunc->
IsA(
"vtkPlane"))
3252 \n // Intersection with plane\
3253 \n float t = intersectRayPlane(ip_vertexPos, rayDir);\
3254 \n vec4 intersection = vec4(ip_vertexPos + t * rayDir, 1.0);\
3255 \n g_intersection = (in_inverseTextureDatasetMatrix[0] * intersection).xyz;\
3256 \n vec4 intersDC = in_projectionMatrix * in_modelViewMatrix * in_volumeMatrix[0] * intersection;\
3257 \n intersDC.xyz /= intersDC.w;\
3258 \n vec4 intersWin = NDCToWindow(intersDC.x, intersDC.y, intersDC.z);\
3259 \n if(intersWin.z >= l_depthValue.x)\
3267 vtkErrorWithObjectMacro(
3268 sliceFunc,
"Implicit function type is not supported by this mapper.");
3274 \n // Compute max number of iterations it will take before we hit\
3275 \n // the termination point\
3277 \n // Abscissa of the point on the depth buffer along the ray.\
3278 \n // point in texture coordinates\
3279 \n vec4 rayTermination = WindowToNDC(gl_FragCoord.x, gl_FragCoord.y, l_depthValue.x);\
3281 \n // From normalized device coordinates to eye coordinates.\
3282 \n // in_projectionMatrix is inversed because of way VT\
3283 \n // From eye coordinates to texture coordinates\
3284 \n rayTermination = ip_inverseTextureDataAdjusted *\
3285 \n in_inverseVolumeMatrix[0] *\
3286 \n in_inverseModelViewMatrix *\
3287 \n in_inverseProjectionMatrix *\
3289 \n g_rayTermination = rayTermination.xyz / rayTermination.w;\
3291 \n // Setup the current segment:\
3292 \n g_dataPos = g_rayOrigin;\
3293 \n g_terminatePos = g_rayTermination;\
3295 \n g_terminatePointMax = length(g_terminatePos.xyz - g_dataPos.xyz) /\
3296 \n length(g_dirStep);\
3297 \n g_currentT = 0.0;");
3307 \n if(any(greaterThan(max(g_dirStep, vec3(0.0))*(g_dataPos - in_texMax[0]),vec3(0.0))) ||\
3308 \n any(greaterThan(min(g_dirStep, vec3(0.0))*(g_dataPos - in_texMin[0]),vec3(0.0))))\
3313 \n // Early ray termination\
3314 \n // if the currently composited colour alpha is already fully saturated\
3315 \n // we terminated the loop or if we have hit an obstacle in the\
3316 \n // direction of they ray (using depth buffer) we terminate as well.\
3317 \n if((g_fragColor.a > g_opacityThreshold) || \
3318 \n g_currentT >= g_terminatePointMax)\
3349 \nuniform float in_croppingPlanes[6];\
3350 \nuniform int in_croppingFlags [32];\
3351 \nfloat croppingPlanesTexture[6];\
3353 \n// X: axis = 0, Y: axis = 1, Z: axis = 2\
3354 \n// cp Cropping plane bounds (minX, maxX, minY, maxY, minZ, maxZ)\
3355 \nint computeRegionCoord(float cp[6], vec3 pos, int axis)\
3357 \n int cpmin = axis * 2;\
3358 \n int cpmax = cpmin + 1;\
3360 \n if (pos[axis] < cp[cpmin])\
3364 \n else if (pos[axis] >= cp[cpmin] &&\
3365 \n pos[axis] < cp[cpmax])\
3369 \n else if (pos[axis] >= cp[cpmax])\
3376 \nint computeRegion(float cp[6], vec3 pos)\
3378 \n return (computeRegionCoord(cp, pos, 0) +\
3379 \n (computeRegionCoord(cp, pos, 1) - 1) * 3 +\
3380 \n (computeRegionCoord(cp, pos, 2) - 1) * 9);\
3394 \n // Convert cropping region to texture space\
3395 \n mat4 datasetToTextureMat = in_inverseTextureDatasetMatrix[0];\
3397 \n vec4 tempCrop = vec4(in_croppingPlanes[0], 0.0, 0.0, 1.0);\
3398 \n tempCrop = datasetToTextureMat * tempCrop;\
3399 \n if (tempCrop[3] != 0.0)\
3401 \n tempCrop[0] /= tempCrop[3];\
3403 \n croppingPlanesTexture[0] = tempCrop[0];\
3405 \n tempCrop = vec4(in_croppingPlanes[1], 0.0, 0.0, 1.0);\
3406 \n tempCrop = datasetToTextureMat * tempCrop;\
3407 \n if (tempCrop[3] != 0.0)\
3409 \n tempCrop[0] /= tempCrop[3];\
3411 \n croppingPlanesTexture[1] = tempCrop[0];\
3413 \n tempCrop = vec4(0.0, in_croppingPlanes[2], 0.0, 1.0);\
3414 \n tempCrop = datasetToTextureMat * tempCrop;\
3415 \n if (tempCrop[3] != 0.0)\
3417 \n tempCrop[1] /= tempCrop[3];\
3419 \n croppingPlanesTexture[2] = tempCrop[1];\
3421 \n tempCrop = vec4(0.0, in_croppingPlanes[3], 0.0, 1.0);\
3422 \n tempCrop = datasetToTextureMat * tempCrop;\
3423 \n if (tempCrop[3] != 0.0)\
3425 \n tempCrop[1] /= tempCrop[3];\
3427 \n croppingPlanesTexture[3] = tempCrop[1];\
3429 \n tempCrop = vec4(0.0, 0.0, in_croppingPlanes[4], 1.0);\
3430 \n tempCrop = datasetToTextureMat * tempCrop;\
3431 \n if (tempCrop[3] != 0.0)\
3433 \n tempCrop[2] /= tempCrop[3];\
3435 \n croppingPlanesTexture[4] = tempCrop[2];\
3437 \n tempCrop = vec4(0.0, 0.0, in_croppingPlanes[5], 1.0);\
3438 \n tempCrop = datasetToTextureMat * tempCrop;\
3439 \n if (tempCrop[3] != 0.0)\
3441 \n tempCrop[2] /= tempCrop[3];\
3443 \n croppingPlanesTexture[5] = tempCrop[2];");
3456 \n // Determine region\
3457 \n int regionNo = computeRegion(croppingPlanesTexture, g_dataPos);\
3459 \n // Do & operation with cropping flags\
3460 \n // Pass the flag that its Ok to sample or not to sample\
3461 \n if (in_croppingFlags[regionNo] == 0)\
3463 \n // Skip this voxel\
3492 \n /// We support only 8 clipping planes for now\
3493 \n /// The first value is the size of the data array for clipping\
3494 \n /// planes (origin, normal)\
3495 \n uniform float in_clippingPlanes[49];\
3496 \n uniform float in_clippedVoxelIntensity;\
3498 \n int clip_numPlanes;\
3499 \n vec3 clip_rayDirObj;\
3500 \n mat4 clip_texToObjMat;\
3501 \n mat4 clip_objToTexMat;\
3503 \n// Tighten the sample range as needed to account for clip planes. \
3504 \n// Arguments are in texture coordinates. \
3505 \n// Returns true if the range is at all valid after clipping. If not, \
3506 \n// the fragment should be discarded. \
3507 \nbool AdjustSampleRangeForClipping(inout vec3 startPosTex, inout vec3 stopPosTex) \
3509 \n vec4 startPosObj = vec4(0.0);\
3511 \n startPosObj = clip_texToObjMat * vec4(startPosTex - g_rayJitter, 1.0);\
3512 \n startPosObj = startPosObj / startPosObj.w;\
3513 \n startPosObj.w = 1.0;\
3516 \n vec4 stopPosObj = vec4(0.0);\
3518 \n stopPosObj = clip_texToObjMat * vec4(stopPosTex, 1.0);\
3519 \n stopPosObj = stopPosObj / stopPosObj.w;\
3520 \n stopPosObj.w = 1.0;\
3523 \n for (int i = 0; i < clip_numPlanes; i = i + 6)\
3525 \n vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\
3526 \n in_clippingPlanes[i + 2],\
3527 \n in_clippingPlanes[i + 3]);\
3528 \n vec3 planeNormal = normalize(vec3(in_clippingPlanes[i + 4],\
3529 \n in_clippingPlanes[i + 5],\
3530 \n in_clippingPlanes[i + 6]));\
3532 \n // Abort if the entire segment is clipped:\
3533 \n // (We can do this before adjusting the term point, since it'll \
3534 \n // only move further into the clipped area)\
3535 \n float startDistance = dot(planeNormal, planeOrigin - startPosObj.xyz);\
3536 \n float stopDistance = dot(planeNormal, planeOrigin - stopPosObj.xyz);\
3537 \n bool startClipped = startDistance > 0.0;\
3538 \n bool stopClipped = stopDistance > 0.0;\
3539 \n if (startClipped && stopClipped)\
3544 \n float rayDotNormal = dot(clip_rayDirObj, planeNormal);\
3545 \n bool frontFace = rayDotNormal > 0.0;\
3547 \n // Move the start position further from the eye if needed:\
3548 \n if (frontFace && // Observing from the clipped side (plane's front face)\
3549 \n startDistance > 0.0) // Ray-entry lies on the clipped side.\
3551 \n // Scale the point-plane distance to the ray direction and update the\
3553 \n float rayScaledDist = startDistance / rayDotNormal;\
3554 \n startPosObj = vec4(startPosObj.xyz + rayScaledDist * clip_rayDirObj, 1.0);\
3555 \n vec4 newStartPosTex = clip_objToTexMat * vec4(startPosObj.xyz, 1.0);\
3556 \n newStartPosTex /= newStartPosTex.w;\
3557 \n startPosTex = newStartPosTex.xyz;\
3558 \n startPosTex += g_rayJitter;\
3561 \n // Move the end position closer to the eye if needed:\
3562 \n if (!frontFace && // Observing from the unclipped side (plane's back face)\
3563 \n stopDistance > 0.0) // Ray-entry lies on the unclipped side.\
3565 \n // Scale the point-plane distance to the ray direction and update the\
3566 \n // termination point.\
3567 \n float rayScaledDist = stopDistance / rayDotNormal;\
3568 \n stopPosObj = vec4(stopPosObj.xyz + rayScaledDist * clip_rayDirObj, 1.0);\
3569 \n vec4 newStopPosTex = clip_objToTexMat * vec4(stopPosObj.xyz, 1.0);\
3570 \n newStopPosTex /= newStopPosTex.w;\
3571 \n stopPosTex = newStopPosTex.xyz;\
3575 \n if (any(greaterThan(startPosTex, in_texMax[0])) ||\
3576 \n any(lessThan(startPosTex, in_texMin[0])))\
3598 \n vec4 tempClip = in_volumeMatrix[0] * vec4(rayDir, 0.0);\
3599 \n if (tempClip.w != 0.0)\
3601 \n tempClip = tempClip/tempClip.w;\
3602 \n tempClip.w = 1.0;\
3604 \n clip_rayDirObj = normalize(tempClip.xyz);");
3609 clip_rayDirObj = normalize(in_projectionDirection);");
3613 \n clip_numPlanes = int(in_clippingPlanes[0]);\
3614 \n clip_texToObjMat = in_volumeMatrix[0] * in_textureDatasetMatrix[0];\
3615 \n clip_objToTexMat = in_inverseTextureDatasetMatrix[0] * in_inverseVolumeMatrix[0];\
3617 \n // Adjust for clipping.\
3618 \n if (!AdjustSampleRangeForClipping(g_rayOrigin, g_rayTermination))\
3619 \n { // entire ray is clipped.\
3623 \n // Update the segment post-clip:\
3624 \n g_dataPos = g_rayOrigin;\
3625 \n g_terminatePos = g_rayTermination;\
3626 \n g_terminatePointMax = length(g_terminatePos.xyz - g_dataPos.xyz) /\
3627 \n length(g_dirStep);\
3650 int vtkNotUsed(maskType))
3652 if (!mask || !maskInput)
3674 \nvec4 maskValue = texture3D(in_mask, g_dataPos);\
3675 \nif(maskValue.r <= 0.0)\
3694 \nuniform float in_maskBlendFactor;\
3695 \nuniform sampler2D in_labelMapTransfer;\
3696 \nuniform float in_mask_scale;\
3697 \nuniform float in_mask_bias;\
3698 \nuniform int in_labelMapNumLabels;\
3715 \nvec4 scalar = texture3D(in_volume[0], g_dataPos);");
3718 if (noOfComponents == 1)
3721 \n scalar.r = scalar.r * in_volume_scale[0].r + in_volume_bias[0].r;\
3722 \n scalar = vec4(scalar.r);");
3728 \n scalar = scalar * in_volume_scale[0] + in_volume_bias[0];");
3735 \nif (in_maskBlendFactor == 0.0)\
3737 \n g_srcColor.a = computeOpacity(scalar);\
3738 \n if (g_srcColor.a > 0)\
3740 \n g_srcColor = computeColor(scalar, g_srcColor.a);\
3745 \n float opacity = computeOpacity(scalar);\
3746 \n // Get the mask value at this same location\
3747 \n vec4 maskValue = texture3D(in_mask, g_dataPos);\
3748 \n maskValue.r = maskValue.r * in_mask_scale + in_mask_bias;\
3749 \n // Quantize the height of the labelmap texture over number of labels\
3750 \n if (in_labelMapNumLabels > 0)\
3753 \n floor(maskValue.r * in_labelMapNumLabels) /\
3754 \n in_labelMapNumLabels;\
3758 \n maskValue.r = 0.0;\
3760 \n if(maskValue.r == 0.0)\
3762 \n g_srcColor.a = opacity;\
3763 \n if (g_srcColor.a > 0)\
3765 \n g_srcColor = computeColor(scalar, g_srcColor.a);\
3770 \n g_srcColor = texture2D(in_labelMapTransfer,\
3771 \n vec2(scalar.r, maskValue.r));\
3772 \n if (g_srcColor.a > 0)\
3774 \n g_srcColor = computeLighting(g_srcColor, 0, maskValue.r);\
3776 \n if (in_maskBlendFactor < 1.0)\
3778 \n vec4 color = opacity > 0 ? computeColor(scalar, opacity) : vec4(0);\
3779 \n g_srcColor = (1.0 - in_maskBlendFactor) * color +\
3780 \n in_maskBlendFactor * g_srcColor;\
3791 return std::string(
"uniform bool in_clampDepthToBackface;\n"
3792 "vec3 l_opaqueFragPos;\n"
3793 "bool l_updateDepth;\n");
3801 \n l_opaqueFragPos = vec3(-1.0);\
3802 \n if(in_clampDepthToBackface)\
3804 \n l_opaqueFragPos = g_dataPos;\
3806 \n l_updateDepth = true;");
3814 \n if(!g_skip && g_srcColor.a > 0.0 && l_updateDepth)\
3816 \n l_opaqueFragPos = g_dataPos;\
3817 \n l_updateDepth = false;\
3826 \n if (l_opaqueFragPos == vec3(-1.0))\
3828 \n gl_FragData[1] = vec4(1.0);\
3832 \n vec4 depthValue = in_projectionMatrix * in_modelViewMatrix *\
3833 \n in_volumeMatrix[0] * in_textureDatasetMatrix[0] *\
3834 \n vec4(l_opaqueFragPos, 1.0);\
3835 \n depthValue /= depthValue.w;\
3836 \n gl_FragData[1] = vec4(vec3(0.5 * (gl_DepthRange.far -\
3837 \n gl_DepthRange.near) * depthValue.z + 0.5 *\
3838 \n (gl_DepthRange.far + gl_DepthRange.near)), 1.0);\
3847 \n vec3 l_isoPos = g_dataPos;");
3855 \n if(!g_skip && g_srcColor.a > 0.0)\
3857 \n l_isoPos = g_dataPos;\
3858 \n g_exit = true; g_skip = true;\
3867 \n vec4 depthValue = in_projectionMatrix * in_modelViewMatrix *\
3868 \n in_volumeMatrix[0] * in_textureDatasetMatrix[0] *\
3869 \n vec4(l_isoPos, 1.0);\
3870 \n gl_FragData[0] = vec4(l_isoPos, 1.0);\
3871 \n gl_FragData[1] = vec4(vec3((depthValue.z/depthValue.w) * 0.5 + 0.5),\
3880 \n initializeRayCast();\
3881 \n castRay(-1.0, -1.0);\
3882 \n finalizeRayCast();");
3887 const std::vector<std::string>& varNames,
const size_t usedNames)
3890 for (
size_t i = 0; i < usedNames; i++)
3892 shader +=
"uniform sampler2D " + varNames[i] +
";\n";
3899 const std::vector<std::string>& varNames,
const size_t usedNames)
3902 for (
size_t i = 0; i < usedNames; i++)
3904 std::stringstream ss;
3906 shader +=
" gl_FragData[" + ss.str() +
"] = texture2D(" + varNames[i] +
", texCoord);\n";
3908 shader +=
" return;\n";
3913 #endif // vtkVolumeShaderComposer_h
std::string ShadingExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents=0)
abstract interface for implicit functions
virtual float GetScatteringAnisotropy()
Get/Set the volume's scattering anisotropy.
std::string RenderToImageImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
represents a volume (data & properties) in a rendered scene
std::string CroppingDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
virtual int GetUseClippedVoxelIntensity()
Set/Get whether to use a fixed intensity value for voxels in the clipped space for gradient calculati...
std::string PreComputeGradientsImpl(vtkRenderer *vtkNotUsed(ren), vtkVolume *vtkNotUsed(vol), int noOfComponents=1, int independentComponents=0)
std::string BaseImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string ClippingImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
Abstract class for a volume mapper.
std::string ComputeGradientOpacityMulti1DDecl(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string ComputeLightingMultiDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vol, int noOfComponents, int independentComponents, int vtkNotUsed(totalNumberOfLights), bool defaultLighting)
std::string DepthPassInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(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::string BaseDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int totalNumberOfLights, int numberPositionalLights, bool defaultLighting, int noOfComponents, int independentComponents)
std::map< int, vtkVolumeInputHelper > VolumeInputMap
std::string PickingActorPassDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(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 RenderToImageDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
bool HasLabelGradientOpacity()
std::string ShadingSingleInput(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType, int noOfComponents, int independentComponents=0)
virtual vtkVolumeProperty * GetProperty()
Set/Get the volume property.
std::string ComputeGradientOpacity1DDecl(vtkVolume *vol, int noOfComponents, int independentComponents, std::map< int, std::string > gradientTableMap)
std::string RenderToImageExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
abstract specification for renderers
std::string BaseInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, bool defaultLighting)
std::string CroppingDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
vtkUnsignedCharArray * GetPointGhostArray()
Gets the array that defines the ghost type of each point.
std::string TerminationExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ShadingDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string BaseDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol), bool multipleInputs)
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.
int GetShade(int index)
Set/Get the shading of a volume.
std::string PickingActorPassExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
virtual vtkDataSet * GetInput()
Set/Get the input data.
OpenGL implementation of volume rendering through ray-casting.
static vtkOpenGLGPUVolumeRayCastMapper * SafeDownCast(vtkObjectBase *o)
std::string ComputeOpacity2DDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, std::map< int, std::string > opacityTableMap, int useGradient)
virtual int GetDisableGradientOpacity(int index)
Enable/Disable the gradient opacity function for the given component.
std::string CroppingImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string TerminationImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ClippingDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string CompositeMaskDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType)
std::string ClippingExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
static vtkRectilinearGrid * SafeDownCast(vtkObjectBase *o)
topologically and geometrically regular array of data
bool HasGradientOpacity(int index=0)
Check whether or not we have the gradient opacity.
static vtkGPUVolumeRayCastMapper * SafeDownCast(vtkObjectBase *o)
std::string WorkerImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
static vtkDataSet * SafeDownCast(vtkObjectBase *o)
std::string ImageSampleImplementationFrag(const std::vector< std::string > &varNames, const size_t usedNames)
std::string ComputeClipPositionImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string PickingIdHigh24PassExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ComputeRayDirectionDeclaration(vtkRenderer *ren, vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int vtkNotUsed(noOfComponents))
std::string ComputeVolumetricShadowDec(vtkOpenGLGPUVolumeRayCastMapper *mapper, vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int useGradYAxis)
std::string GradientCacheDec(vtkRenderer *vtkNotUsed(ren), vtkVolume *vtkNotUsed(vol), vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int independentComponents=0)
virtual vtkTypeBool GetUseJittering()
If UseJittering is on, each ray traversal direction will be perturbed slightly using a noise-texture ...
std::string ShadingInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
represents the common properties for rendering a volume.
virtual vtkTypeBool GetCropping()
Turn On/Off orthogonal cropping.
std::string ShadingDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string CroppingExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ClippingInit(vtkRenderer *ren, vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string Transfer2DDeclaration(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string ComputeColorMultiDeclaration(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, bool useGradientTF)
std::string ComputeTextureCoordinates(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string BinaryMaskImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeTexture *mask, int maskType)
std::string TerminationInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vol)
std::string ComputeMatricesInit(vtkOpenGLGPUVolumeRayCastMapper *vtkNotUsed(mapper), int numberPositionalLights)
std::string ComputeOpacityMultiDeclaration(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string PickingIdLow24PassExit(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 CroppingInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
virtual float GetVolumetricScatteringBlending()
This parameter controls the blending between surfacic approximation and volumetric multi-scattering...
std::string ImageSampleDeclarationFrag(const std::vector< std::string > &varNames, const size_t usedNames)
virtual int GetCurrentPass()
std::string BinaryMaskDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), vtkImageData *maskInput, vtkVolumeTexture *mask, int vtkNotUsed(maskType))
virtual vtkTypeBool GetParallelProjection()
Set/Get the value of the ParallelProjection instance variable.
std::string ComputeOpacityEvaluationCall(vtkOpenGLGPUVolumeRayCastMapper *vtkNotUsed(mapper), vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int noOfComponents, int independentComponents, int useGradYAxis, std::string position, bool requestColor=false)
virtual vtkTypeBool GetUseDepthPass()
If UseDepthPass is on, the mapper will use two passes.
std::string ShadingMultipleInputs(vtkVolumeMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string ComputeColor2DYAxisDeclaration(int noOfComponents, int vtkNotUsed(independentComponents), std::map< int, std::string > colorTableMap)
std::string TerminationDeclarationVertex(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(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 DepthPassExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
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 DepthPassImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
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 BaseExit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string TerminationDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
std::string ComputeGradientDeclaration(vtkOpenGLGPUVolumeRayCastMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs)
std::string ComputeDensityGradientDeclaration(vtkOpenGLGPUVolumeRayCastMapper *mapper, vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap &inputs, int noOfComponents, int independentComponents, int useGradYAxis)
std::string ComputeOpacityDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, std::map< int, std::string > opacityTableMap)
std::string ClippingDeclarationFragment(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *mapper, vtkVolume *vtkNotUsed(vol))
std::string ComputeColorDeclaration(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol), int noOfComponents, int independentComponents, std::map< int, std::string > colorTableMap)
std::string RenderToImageInit(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))