4 #ifndef vtkVolumeShaderComposer_h
5 #define vtkVolumeShaderComposer_h
26 for (
auto& item : inputs)
39 for (
auto& item : inputs)
42 const bool lighting = volProp->
GetShade() == 1;
51 for (
auto& item : inputs)
55 if (useClippedVoxelIntensity)
65 return arrayName.substr(0, arrayName.length() - 3);
77 VTK_ABI_NAMESPACE_BEGIN
83 " //Transform vertex (data coordinates) to clip coordinates\n"
84 " // p_clip = T_ProjViewModel * T_dataToWorld * p_data\n"
85 " vec4 pos = in_projectionMatrix * in_modelViewMatrix * in_volumeMatrix[0] *\n"
86 " vec4(in_vertexPos.xyz, 1.0);\n"
87 " gl_Position = pos;\n");
95 " // Transform vertex (data coordinates) to texture coordinates.\n"
96 " // p_texture = T_dataToTex * p_data\n"
97 " vec3 uvx = sign(in_cellSpacing[0]) * (in_inverseTextureDatasetMatrix[0] *\n"
98 " vec4(in_vertexPos, 1.0)).xyz;\n"
100 " // For point dataset, we offset the texture coordinate\n"
101 " // to account for OpenGL treating voxel at the center of the cell.\n"
102 " // Transform cell tex-coordinates to point tex-coordinates (cellToPoint\n"
103 " // is an identity matrix in the case of cell data).\n"
104 " ip_textureCoords = (in_cellToPoint[0] * vec4(uvx, 1.0)).xyz;\n"
105 " ip_inverseTextureDataAdjusted = in_cellToPoint[0] * in_inverseTextureDatasetMatrix[0];\n");
110 vtkVolume* vtkNotUsed(vol),
bool multipleInputs)
113 const int numInputs = gpuMapper->GetInputCount();
115 std::ostringstream ss;
116 ss <<
"uniform vec3 in_cellSpacing[" << numInputs
118 "uniform mat4 in_modelViewMatrix;\n"
119 "uniform mat4 in_projectionMatrix;\n";
121 const int numTransf = multipleInputs ? numInputs + 1 : 1;
122 ss <<
"uniform mat4 in_volumeMatrix[" << numTransf
124 "uniform mat4 in_inverseTextureDatasetMatrix["
127 "uniform mat4 in_cellToPoint["
131 "//This variable could be 'invariant varying' but it is declared\n"
132 "//as 'varying' to avoid compiler compatibility issues.\n"
133 "out mat4 ip_inverseTextureDataAdjusted;\n";
141 int numberPositionalLights,
bool defaultLighting,
int noOfComponents,
int independentComponents)
143 const int numInputs =
static_cast<int>(inputs.size());
145 std::ostringstream toShaderStr;
146 toShaderStr <<
"uniform sampler3D in_volume[" << numInputs <<
"];\n";
148 toShaderStr <<
"uniform vec4 in_volume_scale[" << numInputs
150 "uniform vec4 in_volume_bias["
151 << numInputs <<
"];\n";
155 toShaderStr <<
"uniform sampler1D in_coordTexs;\n";
156 toShaderStr <<
"uniform vec3 in_coordTexSizes;\n";
157 toShaderStr <<
"uniform vec3 in_coordsScale;\n";
158 toShaderStr <<
"uniform vec3 in_coordsBias;\n";
163 toShaderStr <<
"uniform sampler3D in_blanking;\n";
166 toShaderStr <<
"uniform int in_noOfComponents;\n"
168 "uniform sampler2D in_depthSampler;\n";
173 toShaderStr <<
"uniform sampler2D in_noiseSampler;\n";
178 const int numTransf = (numInputs > 1) ? numInputs + 1 : 1;
179 toShaderStr <<
"uniform mat4 in_volumeMatrix[" << numTransf
181 "uniform mat4 in_inverseVolumeMatrix["
184 "uniform mat4 in_textureDatasetMatrix["
187 "uniform mat4 in_inverseTextureDatasetMatrix["
190 "uniform mat4 in_textureToEye["
193 "uniform vec3 in_texMin["
196 "uniform vec3 in_texMax["
199 "// Eye position in dataset space\n"
200 "uniform vec3 in_eyePosObjs["
203 "uniform mat4 in_cellToPoint["
204 << numTransf <<
"];\n";
206 toShaderStr <<
"// view and model matrices\n"
207 "uniform mat4 in_projectionMatrix;\n"
208 "uniform mat4 in_inverseProjectionMatrix;\n"
209 "uniform mat4 in_modelViewMatrix;\n"
210 "uniform mat4 in_inverseModelViewMatrix;\n"
211 "in mat4 ip_inverseTextureDataAdjusted;\n"
214 "uniform vec3 in_cellStep["
215 << numInputs <<
"];\n";
220 toShaderStr <<
"mat4 g_eyeToTexture = in_inverseTextureDatasetMatrix[0] *"
221 " in_inverseVolumeMatrix[0] * in_inverseModelViewMatrix;\n";
224 if (inputs[0].Volume->GetProperty() && inputs[0].Volume->GetProperty()->GetShade() &&
225 !defaultLighting && totalNumberOfLights > 0)
227 toShaderStr <<
"mat4 g_texToView = in_modelViewMatrix * in_volumeMatrix[0] *"
228 "in_textureDatasetMatrix[0];\n";
231 toShaderStr <<
"uniform vec2 in_scalarsRange[" << numInputs * 4
233 "uniform vec3 in_cellSpacing["
237 "// Sample distance\n"
238 "uniform float in_sampleDistance;\n"
241 "uniform vec2 in_windowLowerLeftCorner;\n"
242 "uniform vec2 in_inverseOriginalWindowSize;\n"
243 "uniform vec2 in_inverseWindowSize;\n"
244 "uniform vec3 in_textureExtentsMax;\n"
245 "uniform vec3 in_textureExtentsMin;\n"
247 "// Material and lighting\n"
248 "uniform vec3 in_diffuse[4];\n"
249 "uniform vec3 in_ambient[4];\n"
250 "uniform vec3 in_specular[4];\n"
251 "uniform float in_shininess[4];\n"
254 "vec3 g_rayJitter = vec3(0.0);\n"
256 "uniform vec2 in_averageIPRange;\n";
258 const bool hasGradientOpacity = HasGradientOpacity(inputs);
259 if (totalNumberOfLights > 0 || hasGradientOpacity)
261 toShaderStr <<
"uniform bool in_twoSidedLighting;\n";
266 toShaderStr << R
"***(
267 uniform float in_giReach;
268 uniform float in_anisotropy;
269 uniform float in_volumetricScatteringBlending;
274 if (totalNumberOfLights > 0)
276 std::string totalLights = std::to_string(totalNumberOfLights);
277 std::string positionalLights = std::to_string(numberPositionalLights);
279 if (!defaultLighting)
281 toShaderStr <<
"#define TOTAL_NUMBER_LIGHTS " << totalLights
283 "#define NUMBER_POS_LIGHTS "
286 "vec4 g_fragWorldPos;\n"
287 "uniform vec3 in_lightAmbientColor[TOTAL_NUMBER_LIGHTS];\n"
288 "uniform vec3 in_lightDiffuseColor[TOTAL_NUMBER_LIGHTS];\n"
289 "uniform vec3 in_lightSpecularColor[TOTAL_NUMBER_LIGHTS];\n"
290 "uniform vec3 in_lightDirection[TOTAL_NUMBER_LIGHTS];\n";
291 if (numberPositionalLights > 0)
293 toShaderStr <<
"uniform vec3 in_lightPosition[NUMBER_POS_LIGHTS];\n"
294 "uniform vec3 in_lightAttenuation[NUMBER_POS_LIGHTS];\n"
295 "uniform float in_lightConeAngle[NUMBER_POS_LIGHTS];\n"
296 "uniform float in_lightExponent[NUMBER_POS_LIGHTS];\n";
301 toShaderStr <<
"vec3 g_lightDirectionTex[TOTAL_NUMBER_LIGHTS];\n";
303 if (numberPositionalLights > 0)
305 toShaderStr <<
"vec3 g_lightPositionTex[NUMBER_POS_LIGHTS];\n";
311 toShaderStr <<
"uniform vec3 in_lightAmbientColor[1];\n"
312 "uniform vec3 in_lightDiffuseColor[1];\n"
313 "uniform vec3 in_lightSpecularColor[1];\n"
314 "vec4 g_lightPosObj["
324 << numInputs <<
"];\n";
328 if (noOfComponents > 1 && independentComponents)
330 toShaderStr <<
"uniform vec4 in_componentWeight;\n";
336 toShaderStr <<
"uniform sampler2D in_depthPassSampler;\n";
341 toShaderStr <<
"#if NUMBER_OF_CONTOURS\n"
342 "uniform float in_isosurfacesValues[NUMBER_OF_CONTOURS];\n"
344 "int findIsoSurfaceIndex(float scalar, float array[NUMBER_OF_CONTOURS+2])\n"
346 " int index = NUMBER_OF_CONTOURS >> 1;\n"
347 " while (scalar > array[index]) ++index;\n"
348 " while (scalar < array[index]) --index;\n"
355 vtkVolume* vol = inputs.begin()->second.Volume;
358 if (func && func->
IsA(
"vtkPlane"))
361 <<
"uniform vec3 in_slicePlaneOrigin;\n"
362 "uniform vec3 in_slicePlaneNormal;\n"
363 "vec3 g_intersection;\n"
365 "float intersectRayPlane(vec3 rayOrigin, vec3 rayDir)\n"
367 " vec4 planeNormal = in_inverseVolumeMatrix[0] * vec4(in_slicePlaneNormal, 0.0);\n"
368 " float denom = dot(planeNormal.xyz, rayDir);\n"
369 " if (abs(denom) > 1e-6)\n"
371 " vec4 planeOrigin = in_inverseVolumeMatrix[0] * vec4(in_slicePlaneOrigin, 1.0);\n"
372 " return dot(planeOrigin.xyz - rayOrigin, planeNormal.xyz) / denom;\n"
379 return toShaderStr.str();
387 vtkVolume* vol = inputs.begin()->second.Volume;
388 const int numInputs =
static_cast<int>(inputs.size());
390 std::ostringstream shaderStr;
396 \n vec2 fragTexCoord2 = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
397 \n in_inverseWindowSize;\
398 \n vec4 depthValue = texture2D(in_depthPassSampler, fragTexCoord2);\
399 \n vec4 rayOrigin = WindowToNDC(gl_FragCoord.x, gl_FragCoord.y, depthValue.x);\
401 \n // From normalized device coordinates to eye coordinates.\
402 \n // in_projectionMatrix is inversed because of way VT\
403 \n // From eye coordinates to texture coordinates\
404 \n rayOrigin = in_inverseTextureDatasetMatrix[0] *\
405 \n in_inverseVolumeMatrix[0] *\
406 \n in_inverseModelViewMatrix *\
407 \n in_inverseProjectionMatrix *\
409 \n rayOrigin /= rayOrigin.w;\
410 \n g_rayOrigin = rayOrigin.xyz;";
415 \n // Get the 3D texture coordinates for lookup into the in_volume dataset\
416 \n g_rayOrigin = ip_textureCoords.xyz;";
420 \n // Getting the ray marching direction (in dataset space)\
421 \n vec3 rayDir = computeRayDirection();\
423 \n // 2D Texture fragment coordinates [0,1] from fragment coordinates.\
424 \n // The frame buffer texture has the size of the plain buffer but \
425 \n // we use a fraction of it. The texture coordinate is less than 1 if\
426 \n // the reduction factor is less than 1.\
427 \n // Device coordinates are between -1 and 1. We need texture\
428 \n // coordinates between 0 and 1. The in_depthSampler\
429 \n // buffer has the original size buffer.\
430 \n vec2 fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
431 \n in_inverseWindowSize;\
433 \n // Multiply the raymarching direction with the step size to get the\
434 \n // sub-step size we need to take at each raymarching step\
435 \n g_dirStep = (ip_inverseTextureDataAdjusted *\
436 \n vec4(rayDir, 0.0)).xyz * in_sampleDistance;\
437 \n g_lengthStep = length(g_dirStep);\
441 \n float jitterValue = 0.0;\
450 \n jitterValue = texture2D(in_noiseSampler, gl_FragCoord.xy /\
451 vec2(textureSize(in_noiseSampler, 0))).x;\
452 \n g_rayJitter = g_dirStep * jitterValue;\
458 \n g_rayJitter = g_dirStep;\
462 \n g_rayOrigin += g_rayJitter;\
467 \n // Flag to determine if voxel should be considered for the rendering\
473 \n // Light position in dataset space";
474 for (
int i = 0; i < numInputs; ++i)
479 << i <<
"] = vec4(in_eyePosObjs[" << (numInputs > 1 ? i + 1 : i) <<
"], 1.0);\
481 << i <<
"] = normalize(g_lightPosObj[" << i <<
"].xyz - ip_vertexPos);\
483 << i <<
"] = normalize(in_eyePosObjs[" << i <<
"].xyz - ip_vertexPos);\
485 << i <<
"] = normalize(g_ldir[" << i <<
"] + g_vdir[" << i <<
"]);";
489 return shaderStr.str();
499 \n g_skip = false;");
505 if (blankPoints || blankCells)
508 \n // Check whether the neighboring points/cells are blank.\
509 \n // Note the half cellStep because texels are point centered.\
510 \n vec3 xvec = vec3(in_cellStep[0].x/2.0, 0.0, 0.0);\
511 \n vec3 yvec = vec3(0.0, in_cellStep[0].y/2.0, 0.0);\
512 \n vec3 zvec = vec3(0.0, 0.0, in_cellStep[0].z/2.0);\
513 \n vec3 texPosPVec[3];\
514 \n texPosPVec[0] = g_dataPos + xvec;\
515 \n texPosPVec[1] = g_dataPos + yvec;\
516 \n texPosPVec[2] = g_dataPos + zvec;\
517 \n vec3 texPosNVec[3];\
518 \n texPosNVec[0] = g_dataPos - xvec;\
519 \n texPosNVec[1] = g_dataPos - yvec;\
520 \n texPosNVec[2] = g_dataPos - zvec;\
521 \n vec4 blankValue = texture3D(in_blanking, g_dataPos);\
522 \n vec4 blankValueXP = texture3D(in_blanking, texPosPVec[0]);\
523 \n vec4 blankValueYP = texture3D(in_blanking, texPosPVec[1]);\
524 \n vec4 blankValueZP = texture3D(in_blanking, texPosPVec[2]);\
525 \n vec4 blankValueXN = texture3D(in_blanking, texPosNVec[0]);\
526 \n vec4 blankValueYN = texture3D(in_blanking, texPosNVec[1]);\
527 \n vec4 blankValueZN = texture3D(in_blanking, texPosNVec[2]);\
528 \n vec3 blankValuePx;\
529 \n blankValuePx[0] = blankValueXP.x;\
530 \n blankValuePx[1] = blankValueYP.x;\
531 \n blankValuePx[2] = blankValueZP.x;\
532 \n vec3 blankValuePy;\
533 \n blankValuePy[0] = blankValueXP.y;\
534 \n blankValuePy[1] = blankValueYP.y;\
535 \n blankValuePy[2] = blankValueZP.y;\
536 \n vec3 blankValueNx;\
537 \n blankValueNx[0] = blankValueXN.x;\
538 \n blankValueNx[1] = blankValueYN.x;\
539 \n blankValueNx[2] = blankValueZN.x;\
540 \n vec3 blankValueNy;\
541 \n blankValueNy[0] = blankValueXN.y;\
542 \n blankValueNy[1] = blankValueYN.y;\
543 \n blankValueNy[2] = blankValueZN.y;\
548 \n // If the current or neighboring points\
549 \n // (that belong to cells that share this texel) are blanked,\
550 \n // skip the texel. In other words, if point 1 were blank,\
551 \n // texels 0, 1 and 2 would have to be skipped.\
552 \n if (blankValue.x > 0.0 ||\
553 \n any(greaterThan(blankValueNx, vec3(0.0))) ||\
554 \n any(greaterThan(blankValuePx, vec3(0.0))))\
556 \n // skip this texel\
563 \n // If the current or previous cells (that share this texel)\
564 \n // are blanked, skip the texel. In other words, if cell 1\
565 \n // is blanked, texels 1 and 2 would have to be skipped.\
566 \n else if (blankValue.y > 0.0 ||\
567 \n any(greaterThan(blankValuePy, vec3(0.0))) ||\
568 \n any(greaterThan(blankValueNy, vec3(0.0))))\
570 \n // skip this texel\
579 \n // If the current or previous cells (that share this texel)\
580 \n // are blanked, skip the texel. In other words, if cell 1\
581 \n // is blanked, texels 1 and 2 would have to be skipped.\
582 \n if (blankValue.x > 0.0 ||\
583 \n any(greaterThan(blankValueNx, vec3(0.0))) ||\
584 \n any(greaterThan(blankValuePx, vec3(0.0))))\
586 \n // skip this texel\
596 \n g_dataPos = g_intersection;\
612 int independentComponents, std::map<int, std::string> gradientTableMap)
615 std::ostringstream ss;
616 if (volProperty->HasGradientOpacity())
618 ss <<
"uniform sampler2D " << ArrayBaseName(gradientTableMap[0]) <<
"[" << noOfComponents
621 bool useLabelGradientOpacity =
622 (volProperty->HasLabelGradientOpacity() && (noOfComponents == 1 || !independentComponents));
623 if (useLabelGradientOpacity)
625 ss <<
"uniform sampler2D in_labelMapGradientOpacity;\n";
630 if (volProperty->HasGradientOpacity() && noOfComponents > 0)
632 if (noOfComponents == 1 || !independentComponents)
635 \nfloat computeGradientOpacity(vec4 grad)\
637 \n return texture2D(" +
638 gradientTableMap[0] +
", vec2(grad.w, 0.0)).r;\
644 \nfloat computeGradientOpacity(vec4 grad, int component)\
647 for (
int i = 0; i < noOfComponents; ++i)
649 std::ostringstream toString;
652 \n if (component == " +
653 toString.str() +
")");
657 \n return texture2D(" +
658 gradientTableMap[i] +
", vec2(grad.w, 0.0)).r;\
667 if (useLabelGradientOpacity)
670 \nfloat computeGradientOpacityForLabel(vec4 grad, float label)\
672 \n return texture2D(in_labelMapGradientOpacity, vec2(grad.w, label)).r;\
683 const bool hasLighting = HasLighting(inputs);
684 const bool hasGradientOp = HasGradientOpacity(inputs);
687 if (hasLighting || hasGradientOp)
690 "// c is short for component\n"
691 "vec4 computeGradient(in vec3 texPos, in int c, in sampler3D volume,in int index)\n"
693 " // Approximate Nabla(F) derivatives with central differences.\n"
694 " vec3 g1; // F_front\n"
695 " vec3 g2; // F_back\n"
696 " vec3 xvec = vec3(in_cellStep[index].x, 0.0, 0.0);\n"
697 " vec3 yvec = vec3(0.0, in_cellStep[index].y, 0.0);\n"
698 " vec3 zvec = vec3(0.0, 0.0, in_cellStep[index].z);\n"
699 " vec3 texPosPvec[3];\n"
700 " texPosPvec[0] = texPos + xvec;\n"
701 " texPosPvec[1] = texPos + yvec;\n"
702 " texPosPvec[2] = texPos + zvec;\n"
703 " vec3 texPosNvec[3];\n"
704 " texPosNvec[0] = texPos - xvec;\n"
705 " texPosNvec[1] = texPos - yvec;\n"
706 " texPosNvec[2] = texPos - zvec;\n"
707 " g1.x = texture3D(volume, vec3(texPosPvec[0]))[c];\n"
708 " g1.y = texture3D(volume, vec3(texPosPvec[1]))[c];\n"
709 " g1.z = texture3D(volume, vec3(texPosPvec[2]))[c];\n"
710 " g2.x = texture3D(volume, vec3(texPosNvec[0]))[c];\n"
711 " g2.y = texture3D(volume, vec3(texPosNvec[1]))[c];\n"
712 " g2.z = texture3D(volume, vec3(texPosNvec[2]))[c];\n"
717 std::string(
" vec4 g1ObjDataPos[3], g2ObjDataPos[3];\n"
718 " for (int i = 0; i < 3; ++i)\n"
720 " g1ObjDataPos[i] = clip_texToObjMat * vec4(texPosPvec[i], 1.0);\n"
721 " if (g1ObjDataPos[i].w != 0.0)\n"
723 " g1ObjDataPos[i] /= g1ObjDataPos[i].w;\n"
725 " g2ObjDataPos[i] = clip_texToObjMat * vec4(texPosNvec[i], 1.0);\n"
726 " if (g2ObjDataPos[i].w != 0.0)\n"
728 " g2ObjDataPos[i] /= g2ObjDataPos[i].w;\n"
732 " for (int i = 0; i < clip_numPlanes && !g_skip; i = i + 6)\n"
734 " vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\n"
735 " in_clippingPlanes[i + 2],\n"
736 " in_clippingPlanes[i + 3]);\n"
737 " vec3 planeNormal = normalize(vec3(in_clippingPlanes[i + 4],\n"
738 " in_clippingPlanes[i + 5],\n"
739 " in_clippingPlanes[i + 6]));\n"
740 " for (int j = 0; j < 3; ++j)\n"
742 " if (dot(vec3(planeOrigin - g1ObjDataPos[j].xyz), planeNormal) > 0)\n"
744 " g1[j] = in_clippedVoxelIntensity;\n"
746 " if (dot(vec3(planeOrigin - g2ObjDataPos[j].xyz), planeNormal) > 0)\n"
748 " g2[j] = in_clippedVoxelIntensity;\n"
754 shaderStr +=
std::string(
" // Apply scale and bias to the fetched values.\n"
755 " g1 = g1 * in_volume_scale[index][c] + in_volume_bias[index][c];\n"
756 " g2 = g2 * in_volume_scale[index][c] + in_volume_bias[index][c];\n"
761 std::string(
" // Central differences: (F_front - F_back) / 2h\n"
762 " // This version of computeGradient() is only used for lighting\n"
763 " // calculations (only direction matters), hence the difference is\n"
764 " // not scaled by 2h and a dummy gradient mag is returned (-1.).\n"
765 " return vec4((g1 - g2) / in_cellSpacing[index], -1.0);\n"
771 " // Scale values the actual scalar range.\n"
772 " float range = in_scalarsRange[4*index+c][1] - in_scalarsRange[4*index+c][0];\n"
773 " g1 = in_scalarsRange[4*index+c][0] + range * g1;\n"
774 " g2 = in_scalarsRange[4*index+c][0] + range * g2;\n"
776 " // Central differences: (F_front - F_back) / 2h\n"
779 " float avgSpacing = (in_cellSpacing[index].x +\n"
780 " in_cellSpacing[index].y + in_cellSpacing[index].z) / 3.0;\n"
781 " vec3 aspect = in_cellSpacing[index] * 2.0 / avgSpacing;\n"
783 " float grad_mag = length(g2);\n"
785 " // Handle normalizing with grad_mag == 0.0\n"
786 " g2 = grad_mag > 0.0 ? normalize(g2) : vec3(0.0);\n"
788 " // Since the actual range of the gradient magnitude is unknown,\n"
789 " // assume it is in the range [0, 0.25 * dataRange].\n"
790 " range = range != 0 ? range : 1.0;\n"
791 " grad_mag = grad_mag / (0.25 * range);\n"
792 " grad_mag = clamp(grad_mag, 0.0, 1.0);\n"
794 " return vec4(g2.xyz, grad_mag);\n"
801 "vec4 computeGradient(in vec3 texPos, in int c, in sampler3D volume, in int index)\n"
803 " return vec4(0.0);\n"
816 for(int i=0; i<TOTAL_NUMBER_LIGHTS; i++)
818 g_lightDirectionTex[i] = (g_eyeToTexture * vec4(-in_lightDirection[i], 0.0)).xyz;
822 if (numberPositionalLights > 0)
825 for(int i=0; i<NUMBER_POS_LIGHTS; i++)
827 g_lightPositionTex[i] = (g_eyeToTexture * vec4(in_lightPosition[i], 1.0)).xyz;
837 int independentComponents, std::map<int, std::string> opacityTableMap,
int useGradient)
841 bool severalIndpt = noOfComponents > 1 && independentComponents;
843 ?
"vec4 computeRGBAWithGrad(vec4 scalar, vec4 grad, int component)\n"
844 :
"vec4 computeRGBAWithGrad(vec4 scalar, vec4 grad)\n";
853 "vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
854 "for (int i = 0; i < 4; ++i)\n"
856 " yscalar[i] = yscalar[i] * in_transfer2DYAxis_scale[i] + in_transfer2DYAxis_bias[i];\n"
860 for (
int i = 0; i < noOfComponents; ++i)
866 :
std::string(
"yscalar[") + std::to_string(i) +
"]");
868 functionBody +=
" if(component == " + std::to_string(i) +
871 " return texture2D(" +
872 opacityTableMap[i] +
",\n" +
" vec2(scalar[" + std::to_string(i) +
"], " + secondAxis +
877 else if (noOfComponents == 2 && !independentComponents)
879 std::string secondAxis(useGradient ?
"grad.w" :
"yscalar.y");
881 functionBody +=
" return texture2D(" + opacityTableMap[0] +
884 secondAxis +
"));\n";
892 functionBody +=
" return texture2D(" + opacityTableMap[0] +
894 " vec2(scalar.a, grad.w));\n";
900 " vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
901 " yscalar.r = yscalar.r * in_transfer2DYAxis_scale.r + in_transfer2DYAxis_bias.r;\n"
902 " yscalar = vec4(yscalar.r);\n"
903 " return texture2D(" +
906 " vec2(scalar.a, yscalar.w));\n";
910 resStr = functionSignature +
"{\n" + functionBody +
"}\n";
918 int independentComponents,
int useGradYAxis,
std::string position,
bool requestColor =
false)
924 if (inputs.size() > 1)
927 const bool hasGradOp = ::HasGradientOpacity(inputs);
928 resStr +=
" opacity = computeOpacity(vec4(scalar), opacityTF);\n";
933 resStr +=
std::string(
" gradient = computeGradient(") + position +
", c, volume, index);\n";
934 resStr +=
" opacity *= computeGradientOpacity(gradient, gradTF);\n";
940 vtkGenericWarningMacro(<<
"ComputeOpacityEvaluationCall was called with requestColor, but "
941 "MultiVolume does not support this option yet.");
954 bool indpComps = (noOfComponents > 1 && independentComponents);
964 resStr +=
std::string(
" opacity = computeOpacity(vec4(scalar)") + compArgument +
967 if (hasGradOp || useLabelGradientOpacity)
969 resStr +=
std::string(
" gradient = computeGradient(") + position +
971 " if(gradient.w >= 0.0) {\n") +
972 (hasGradOp ? (
std::string(
" opacity *= computeGradientOpacity(gradient") +
973 compArgument +
")" + compWeights +
";\n")
976 + (useLabelGradientOpacity
977 ? (std::string(
" opacity *= computeGradientOpacityForLabel(gradient, label);\n"))
980 + std::string(
" }\n");
986 " color = texture2D(" + inputs[0].RGBTablesMap[0] +
", vec2(scalar, 0.0)).xyz;\n";
995 std::string(
" gradient = computeGradient(") + position +
", c, volume, index);\n";
997 resStr +=
std::string(
" vec4 lutRes = computeRGBAWithGrad(vec4(scalar), gradient") +
1000 resStr +=
" opacity = lutRes.a;\n";
1004 resStr +=
" color = lutRes.xyz;\n";
1015 int independentComponents,
int useGradYAxis)
1017 const bool hasLighting = ::HasLighting(inputs);
1018 const bool hasGradientOp = ::HasGradientOpacity(inputs);
1022 if (inputs.size() > 1)
1027 "vec4 computeDensityGradient(in vec3 texPos, in int c, in sampler3D volume, "
1028 "const in sampler2D opacityTF, const in sampler2D gradTF, in int index, float label)\n");
1033 std::string(
"vec4 computeDensityGradient(in vec3 texPos, in int c, in sampler3D volume, "
1034 "const in sampler2D opacityTF, in int index, float label)\n");
1039 functionSignature =
std::string(
"vec4 computeDensityGradient(in vec3 texPos, in int c, in "
1040 "sampler3D volume, in int index, float label)\n");
1044 if (hasLighting || hasGradientOp)
1050 static const std::array<std::pair<const char*, const char*>, 6> results_texPos = { {
1051 {
" g1.x",
"texPosPvec[0]" },
1052 {
" g1.y",
"texPosPvec[1]" },
1053 {
" g1.z",
"texPosPvec[2]" },
1054 {
" g2.x",
"texPosNvec[0]" },
1055 {
" g2.y",
"texPosNvec[1]" },
1056 {
" g2.z",
"texPosNvec[2]" },
1059 shaderStr +=
std::string(
"// c is short for component\n") + functionSignature +
1061 " // Approximate Nabla(F) derivatives with central differences.\n"
1062 " vec3 g1; // F_front\n"
1063 " vec3 g2; // F_back\n"
1064 " vec3 xvec = vec3(in_cellStep[index].x, 0.0, 0.0);\n"
1065 " vec3 yvec = vec3(0.0, in_cellStep[index].y, 0.0);\n"
1066 " vec3 zvec = vec3(0.0, 0.0, in_cellStep[index].z);\n"
1067 " vec3 texPosPvec[3];\n"
1068 " texPosPvec[0] = texPos + xvec;\n"
1069 " texPosPvec[1] = texPos + yvec;\n"
1070 " texPosPvec[2] = texPos + zvec;\n"
1071 " vec3 texPosNvec[3];\n"
1072 " texPosNvec[0] = texPos - xvec;\n"
1073 " texPosNvec[1] = texPos - yvec;\n"
1074 " texPosNvec[2] = texPos - zvec;\n"
1080 for (
auto& gradComp : results_texPos)
1084 mapper, inputs, noOfComponents, independentComponents, useGradYAxis, gradComp.second);
1085 shaderStr +=
std::string(
" scalar = texture3D(volume,") + gradComp.second +
1087 " scalar = scalar * in_volume_scale[index][c] + in_volume_bias[index][c];\n") +
1088 opacityTFcall + gradComp.first +
" = opacity;\n";
1094 std::string(
" vec4 g1ObjDataPos[3], g2ObjDataPos[3];\n"
1095 " for (int i = 0; i < 3; ++i)\n"
1097 " g1ObjDataPos[i] = clip_texToObjMat * vec4(texPosPvec[i], 1.0);\n"
1098 " if (g1ObjDataPos[i].w != 0.0)\n"
1100 " g1ObjDataPos[i] /= g1ObjDataPos[i].w;\n"
1102 " g2ObjDataPos[i] = clip_texToObjMat * vec4(texPosNvec[i], 1.0);\n"
1103 " if (g2ObjDataPos[i].w != 0.0)\n"
1105 " g2ObjDataPos[i] /= g2ObjDataPos[i].w;\n"
1109 " for (int i = 0; i < clip_numPlanes && !g_skip; i = i + 6)\n"
1111 " vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\n"
1112 " in_clippingPlanes[i + 2],\n"
1113 " in_clippingPlanes[i + 3]);\n"
1114 " vec3 planeNormal = normalize(vec3(in_clippingPlanes[i + 4],\n"
1115 " in_clippingPlanes[i + 5],\n"
1116 " in_clippingPlanes[i + 6]));\n"
1117 " for (int j = 0; j < 3; ++j)\n"
1119 " if (dot(vec3(planeOrigin - g1ObjDataPos[j].xyz), planeNormal) > 0)\n"
1121 " g1[j] = in_clippedVoxelIntensity;\n"
1123 " if (dot(vec3(planeOrigin - g2ObjDataPos[j].xyz), planeNormal) > 0)\n"
1125 " g2[j] = in_clippedVoxelIntensity;\n"
1135 std::string(
" // Central differences: (F_front - F_back) / 2h\n"
1136 " // This version of computeGradient() is only used for lighting\n"
1137 " // calculations (only direction matters), hence the difference is\n"
1138 " // not scaled by 2h and a dummy gradient mag is returned (-1.).\n"
1139 " return vec4((g1 - g2) / in_cellSpacing[index], -1.0);\n"
1145 " // Scale values the actual scalar range.\n"
1146 " float range = in_scalarsRange[4*index+c][1] - in_scalarsRange[4*index+c][0];\n"
1147 " g1 = in_scalarsRange[4*index+c][0] + range * g1;\n"
1148 " g2 = in_scalarsRange[4*index+c][0] + range * g2;\n"
1150 " // Central differences: (F_front - F_back) / 2h\n"
1153 " float avgSpacing = (in_cellSpacing[index].x +\n"
1154 " in_cellSpacing[index].y + in_cellSpacing[index].z) / 3.0;\n"
1155 " vec3 aspect = in_cellSpacing[index] * 2.0 / avgSpacing;\n"
1157 " float grad_mag = length(g2);\n"
1159 " // Handle normalizing with grad_mag == 0.0\n"
1160 " g2 = grad_mag > 0.0 ? normalize(g2) : vec3(0.0);\n"
1162 " // Since the actual range of the gradient magnitude is unknown,\n"
1163 " // assume it is in the range [0, 0.25 * dataRange].\n"
1164 " range = range != 0 ? range : 1.0;\n"
1165 " grad_mag = grad_mag / (0.25 * range);\n"
1166 " grad_mag = clamp(grad_mag, 0.0, 1.0);\n"
1168 " return vec4(g2.xyz, grad_mag);\n"
1174 shaderStr += functionSignature +
1176 " return vec4(0.0);\n"
1193 float phase_function(float cos_angle)
1202 float g_anisotropy2 = in_anisotropy * in_anisotropy;
1204 float phase_function(float cos_angle)
1206 float d = 1.0 + g_anisotropy2 - 2.0 * in_anisotropy * cos_angle;
1207 return (1.0 - g_anisotropy2) / (d * sqrt(d));
1217 vtkVolume* vol,
int noOfComponents,
int independentComponents,
int totalNumberOfLights,
1218 int numberPositionalLights,
bool defaultLighting)
1223 \nvec4 computeLighting(vec4 color, int component, float label)\
1225 \n vec4 finalColor = vec4(0.0);\n");
1228 int const shadeReqd = volProperty->
GetShade() &&
1235 bool const volumetricShadow = glMapper->GetVolumetricScatteringBlending() > 0.0;
1237 ?
"\n vol_shadow = volumeShadow(g_dataPos, tex_light.xyz, 0.0, component, in_volume[0], "
1241 volumetricShadow ?
"\n float vol_shadow = 1.0;\n vec4 tex_light = vec4(0.0);\n" :
"\n";
1246 if (glMapper->GetComputeNormalFromOpacity())
1250 std::string(
" vec4 shading_gradient = computeDensityGradient(g_dataPos, component, "
1251 "in_volume[0], 0, label);\n");
1257 " vec4 shading_gradient = computeGradient(g_dataPos, component, in_volume[0], 0);\n");
1265 if (!shadeReqd || glMapper->GetComputeNormalFromOpacity())
1268 std::string(
" vec4 gradient = computeGradient(g_dataPos, component, in_volume[0], 0);\n");
1273 shaderStr +=
std::string(
" vec4 gradient = shading_gradient;\n");
1279 if (defaultLighting)
1282 vec3 diffuse = vec3(0.0);
1283 vec3 specular = vec3(0.0);
1284 vec3 normal = shading_gradient.xyz;
1285 float normalLength = length(normal);
1286 if (normalLength > 0.0)
1288 normal = normalize(normal);
1292 normal = vec3(0.0, 0.0, 0.0);
1294 // XXX: normal is oriented inside the volume, so we take -g_ldir/-g_vdir
1295 float nDotL = dot(normal, -g_ldir[0]);
1296 vec3 r = normalize(2.0 * nDotL * normal + g_ldir[0]);
1297 float vDotR = dot(r, -g_vdir[0]);
1298 if (nDotL < 0.0 && in_twoSidedLighting)
1304 diffuse = nDotL * in_diffuse[component] *
1305 in_lightDiffuseColor[0] * color.rgb;
1306 vDotR = max(vDotR, 0.0);
1307 specular = pow(vDotR, in_shininess[component]) *
1308 in_specular[component] *
1309 in_lightSpecularColor[0];
1311 // For the headlight, ignore the light's ambient color
1312 // for now as it is causing the old mapper tests to fail
1313 finalColor.xyz = in_ambient[component] * color.rgb +
1318 else if (totalNumberOfLights > 0)
1321 g_fragWorldPos = g_texToView * vec4(g_dataPos, 1.0);
1322 if (g_fragWorldPos.w != 0.0)
1324 g_fragWorldPos /= g_fragWorldPos.w;
1326 vec3 viewDirection = normalize(-g_fragWorldPos.xyz);
1327 vec3 ambient = vec3(0,0,0);
1328 vec3 diffuse = vec3(0,0,0);
1329 vec3 specular = vec3(0,0,0);
1330 vec3 vertLightDirection;
1331 vec3 normal = normalize((in_textureToEye[0] * vec4(shading_gradient.xyz, 0.0)).xyz);
1335 if (numberPositionalLights > 0)
1338 for (int posNum = 0; posNum < NUMBER_POS_LIGHTS; posNum++)
1340 float attenuation = 1.0;
1341 lightDir = in_lightDirection[posNum];
1342 vertLightDirection = (g_fragWorldPos.xyz - in_lightPosition[posNum]);
1343 float distance = length(vertLightDirection);
1344 vertLightDirection = normalize(vertLightDirection);
1346 (in_lightAttenuation[posNum].x
1347 + in_lightAttenuation[posNum].y * distance
1348 + in_lightAttenuation[posNum].z * distance * distance);
1349 // per OpenGL standard cone angle is 90 or less for a spot light
1350 if (in_lightConeAngle[posNum] <= 90.0)
1352 float coneDot = dot(vertLightDirection, lightDir);
1353 // if inside the cone
1354 if (coneDot >= cos(radians(in_lightConeAngle[posNum])))
1356 attenuation = attenuation * pow(coneDot, in_lightExponent[posNum]);
1364 float nDotL = dot(normal, vertLightDirection);
1365 if (nDotL < 0.0 && in_twoSidedLighting)
1371 float df = max(0.0, attenuation * nDotL);
1372 diffuse += (df * in_lightDiffuseColor[posNum]);
1373 vec3 r = normalize(2.0 * nDotL * normal - vertLightDirection);
1374 float rDotV = dot(-viewDirection, r);
1375 if (rDotV < 0.0 && in_twoSidedLighting)
1381 float sf = attenuation * pow(rDotV, in_shininess[component]);
1382 specular += (sf * in_lightSpecularColor[posNum]);
1385 ambient += in_lightAmbientColor[posNum];
1391 for (int dirNum = NUMBER_POS_LIGHTS; dirNum < TOTAL_NUMBER_LIGHTS; dirNum++)
1393 vertLightDirection = in_lightDirection[dirNum];
1394 float nDotL = dot(normal, vertLightDirection);
1395 if (nDotL < 0.0 && in_twoSidedLighting)
1401 float df = max(0.0, nDotL);
1402 diffuse += (df * in_lightDiffuseColor[dirNum]);
1403 vec3 r = normalize(2.0 * nDotL * normal - vertLightDirection);
1404 float rDotV = dot(-viewDirection, r);
1407 float sf = pow(rDotV, in_shininess[component]);
1408 specular += (sf * in_lightSpecularColor[dirNum]);
1411 ambient += in_lightAmbientColor[dirNum];
1413 finalColor.xyz = in_ambient[component] * ambient +
1414 in_diffuse[component] * diffuse * color.rgb +
1415 in_specular[component] * specular;
1422 shaderStr +=
std::string(
"\n finalColor = vec4(color.rgb, 0.0);");
1425 if (glMapper->GetVolumetricScatteringBlending() > 0.0 && totalNumberOfLights > 0)
1428 float vsBlend = glMapper->GetVolumetricScatteringBlending();
1430 (vsBlend < 1.0 ?
"2.0 * in_volumetricScatteringBlending * exp( - 2.0 * "
1431 "in_volumetricScatteringBlending * shading_gradient.w * color.a)"
1432 :
"2.0 * (1.0 - in_volumetricScatteringBlending) * exp( - 2.0 * "
1433 "in_volumetricScatteringBlending * shading_gradient.w * color.a) + 2.0 * "
1434 "in_volumetricScatteringBlending - 1.0") +
1441 "vec3 view_tdir = normalize((g_eyeToTexture * vec4(viewDirection, 0.0)).xyz);\n")) +
1443 vec3 secondary_contrib = vec3(0.0);
1444 vec3 tex_light = vec3(0.0);
1445 shading_gradient.w = length(shading_gradient.xyz);
1446 vec3 diffuse_light = vec3(0.0);
1447 float attenuation = 0.0;
1448 float vol_shadow = 0.0;
1452 if (defaultLighting)
1455 tex_light = (in_inverseTextureDatasetMatrix[0] * vec4(in_eyePosObjs[0], 1.0)).xyz;
1456 phase = phase_function(-1); // always angle of pi
1457 vol_shadow = volumeShadow(g_dataPos, tex_light, 1.0, component, in_volume[0], 0, label);
1458 secondary_contrib += vol_shadow * phase * color.rgb * in_diffuse[component] * in_lightDiffuseColor[0];
1459 secondary_contrib += in_ambient[component] * in_lightAmbientColor[0];
1464 if (numberPositionalLights > 0)
1467 float dist_light = 0.0;
1468 for(int posNum = 0; posNum < NUMBER_POS_LIGHTS; posNum++)
1470 tex_light = g_lightPositionTex[posNum];
1471 vec3 light_vert = g_fragWorldPos.xyz - in_lightPosition[posNum];
1472 dist_light = length(light_vert);
1473 float light_angle = dot(normalize(light_vert), normalize(in_lightDirection[posNum]));
1474 phase = phase_function(dot(normalize(g_dataPos - tex_light), view_tdir));
1476 (in_lightAttenuation[posNum].x
1477 + in_lightAttenuation[posNum].y * dist_light
1478 + in_lightAttenuation[posNum].z * dist_light * dist_light);
1479 attenuation *= max(0.0, sign(light_angle - cos(radians(in_lightConeAngle[posNum]))))
1480 * pow(light_angle, in_lightExponent[posNum]);
1481 vol_shadow = volumeShadow(g_dataPos, tex_light, 1.0, component, in_volume[0], 0, label);
1482 secondary_contrib += vol_shadow * phase * attenuation * color.rgb * in_diffuse[component] * in_lightDiffuseColor[posNum];
1483 secondary_contrib += in_ambient[component] * in_lightAmbientColor[posNum];
1489 for(int dirNum = NUMBER_POS_LIGHTS; dirNum < TOTAL_NUMBER_LIGHTS; dirNum++)
1491 tex_light = g_lightDirectionTex[dirNum];
1492 phase = phase_function(dot(normalize(-tex_light), view_tdir));
1493 vol_shadow = volumeShadow(g_dataPos, tex_light, 0.0, component, in_volume[0], 0, label);
1494 secondary_contrib += vol_shadow * phase * color.rgb * in_diffuse[component] * in_lightDiffuseColor[dirNum];
1495 secondary_contrib += in_ambient[component] * in_lightAmbientColor[dirNum];
1500 shaderStr += blendingFormula +
1502 finalColor.xyz = (1.0 - vol_coef) * finalColor.xyz + vol_coef * secondary_contrib;
1512 if (noOfComponents == 1 || !independentComponents)
1517 \n if (gradient.w >= 0.0 && label == 0.0)\
1519 \n color.a *= computeGradientOpacity(gradient);\
1525 \n if (gradient.w >= 0.0 && label > 0.0)\
1527 \n color.a *= computeGradientOpacityForLabel(gradient, label);\
1531 else if (noOfComponents > 1 && independentComponents && volProperty->
HasGradientOpacity())
1534 \n if (gradient.w >= 0.0)\
1536 \n for (int i = 0; i < in_noOfComponents; ++i)\
1538 \n color.a = color.a *\
1539 \n computeGradientOpacity(gradient, i) * in_componentWeight[i];\
1546 \n finalColor.a = color.a;\
1547 \n return finalColor;\
1556 int vtkNotUsed(totalNumberOfLights),
bool defaultLighting)
1566 \nvec4 computeLighting(vec3 texPos, vec4 color, const in sampler2D gradientTF, const in sampler3D volume, const in sampler2D opacityTF, const int volIdx, int component)\
1568 \n vec4 finalColor = vec4(0.0);\n");
1573 \nvec4 computeLighting(vec3 texPos, vec4 color, const in sampler3D volume, const in sampler2D opacityTF, const int volIdx, int component)\
1575 \n vec4 finalColor = vec4(0.0);\n");
1579 int const shadeReqd = volProperty->
GetShade() &&
1593 if (glMapper->GetComputeNormalFromOpacity())
1597 shaderStr +=
" vec4 shading_gradient = computeDensityGradient(texPos, component, volume, "
1598 "opacityTF, gradientTF, volIdx, 0.0);\n";
1602 shaderStr +=
" vec4 shading_gradient = computeDensityGradient(texPos, component, volume, "
1603 "opacityTF, volIdx, 0.0);\n";
1609 " vec4 shading_gradient = computeGradient(texPos, component, volume, volIdx);\n";
1616 if (!shadeReqd || glMapper->GetComputeNormalFromOpacity())
1618 shaderStr +=
" vec4 gradient = computeGradient(texPos, component, volume, volIdx);\n";
1623 shaderStr +=
" vec4 gradient = shading_gradient;\n";
1627 if (shadeReqd && defaultLighting)
1630 \n vec3 diffuse = vec3(0.0);\
1631 \n vec3 specular = vec3(0.0);\
1632 \n vec3 normal = shading_gradient.xyz;\
1633 \n float normalLength = length(normal);\
1634 \n if (normalLength > 0.0)\
1636 \n normal = normalize(normal);\
1640 \n normal = vec3(0.0, 0.0, 0.0);\
1642 \n // normal is oriented inside the volume (because normal = gradient, oriented inside the volume)\
1643 \n // thus we have to take minus everything\
1644 \n float nDotL = dot(normal, -g_ldir[volIdx]);\
1645 \n vec3 r = normalize(2.0 * nDotL * normal + g_ldir[volIdx]);\
1646 \n float vDotR = dot(r, -g_vdir[volIdx]);\
1647 \n if (nDotL < 0.0 && in_twoSidedLighting)\
1651 \n if (nDotL > 0.0)\
1653 \n diffuse = nDotL * in_diffuse[component] *\
1654 \n in_lightDiffuseColor[0] * color.rgb;\
1655 \n vDotR = max(vDotR, 0.0);\
1656 \n specular = pow(vDotR, in_shininess[component]) *\
1657 \n in_specular[component] *\
1658 \n in_lightSpecularColor[0];\
1660 \n // For the headlight, ignore the light's ambient color\
1661 \n // for now as it is causing the old mapper tests to fail\
1662 \n finalColor.xyz = in_ambient[component] * color.rgb +\
1663 \n diffuse + specular;\
1668 shaderStr +=
std::string(
"\n finalColor = vec4(color.rgb, 0.0);");
1675 if (volProperty->
HasGradientOpacity() && (noOfComponents == 1 || !independentComponents))
1678 \n if (gradient.w >= 0.0)\
1680 \n color.a = color.a *\
1681 \n computeGradientOpacity(gradient, gradientTF);\
1687 \n finalColor.a = color.a;\
1688 \n return clamp(finalColor, 0.0, 1.0);\
1701 \nvec3 computeRayDirection()\
1703 \n return normalize(ip_vertexPos.xyz - in_eyePosObjs[0].xyz);\
1709 \nuniform vec3 in_projectionDirection;\
1710 \nvec3 computeRayDirection()\
1712 \n return normalize((in_inverseVolumeMatrix[0] *\
1713 \n vec4(in_projectionDirection, 0.0)).xyz);\
1723 if (inputs.size() > 1)
1726 for (
auto& item : inputs)
1728 const auto& prop = item.second.Volume->GetProperty();
1732 auto& map = item.second.RGBTablesMap;
1733 const auto numComp = map.size();
1735 "uniform sampler2D " + ArrayBaseName(map[0]) +
"[" + std::to_string(numComp) +
"];\n";
1743 resStr +=
"uniform sampler2D " + ArrayBaseName(inputs[0].RGBTablesMap[0]) +
"[" +
1744 std::to_string(noOfComponents) +
"];\n";
1754 int independentComponents, std::map<int, std::string> colorTableMap)
1756 std::ostringstream ss;
1759 if (noOfComponents == 1)
1762 \nvec4 computeColor(vec4 scalar, float opacity)\
1764 \n return clamp(computeLighting(vec4(texture2D(" +
1765 colorTableMap[0] +
",\
1766 \n vec2(scalar.w, 0.0)).xyz, opacity), 0, 0.0), 0.0, 1.0);\
1770 else if (noOfComponents > 1 && independentComponents)
1772 std::ostringstream toString;
1775 \nvec4 computeColor(vec4 scalar, float opacity, int component)\
1778 for (
int i = 0; i < noOfComponents; ++i)
1782 \n if (component == " +
1783 toString.str() +
")");
1787 \n return clamp(computeLighting(vec4(texture2D(\
1792 toString.str() +
"],0.0)).xyz,\
1794 toString.str() +
", 0.0), 0.0, 1.0);\
1805 else if (noOfComponents == 2 && !independentComponents)
1808 \nvec4 computeColor(vec4 scalar, float opacity)\
1810 \n return clamp(computeLighting(vec4(texture2D(" +
1811 colorTableMap[0] +
",\
1812 \n vec2(scalar.x, 0.0)).xyz,\
1813 \n opacity), 0, 0.0), 0.0, 1.0);\
1820 \nvec4 computeColor(vec4 scalar, float opacity)\
1822 \n return clamp(computeLighting(vec4(scalar.xyz, opacity), 0, 0.0), 0.0, 1.0);\
1832 std::ostringstream ss;
1834 std::map<int, std::string> lastColorTableMap;
1835 for (
auto& item : inputs)
1837 auto prop = item.second.Volume->GetProperty();
1840 auto& map = item.second.RGBTablesMap;
1841 lastComponentMode = item.second.ComponentMode;
1842 lastColorTableMap = map;
1847 ss <<
"vec4 computeColor(vec4 scalar, const in sampler2D colorTF)\
1849 \n return clamp(computeLighting(vec4(texture2D(colorTF,\
1850 \n vec2(scalar.w, 0.0)).xyz, opacity), 0), 0.0, 1.0);\
1855 std::ostringstream colorDec;
1856 colorDec <<
" vec3 color = ";
1860 colorDec <<
"scalar.xyz;\n";
1867 colorDec <<
"texture2D(colorTF, vec2(scalar.w, 0.0)).xyz;\n";
1873 <<
"vec4 computeColor(vec3 texPos, vec4 scalar, float opacity, const in sampler2D colorTF, "
1874 "const in sampler2D gradientTF, const in sampler3D volume, const in sampler2D "
1875 "opacityTF, const int volIdx)\n\n"
1877 ss << colorDec.str()
1878 <<
" return clamp(computeLighting(texPos, vec4(color, opacity), gradientTF, volume, "
1880 "volIdx, 0), 0.0, 1.0);\n"
1886 <<
"vec4 computeColor(vec3 texPos, vec4 scalar, float opacity, const in sampler2D colorTF, "
1887 "const in sampler3D volume, const in sampler2D opacityTF, const int volIdx)\n\n"
1889 ss << colorDec.str()
1890 <<
" return clamp(computeLighting(texPos, vec4(color, opacity), volume, opacityTF,"
1891 "volIdx, 0), 0.0, 1.0);\n"
1903 std::ostringstream ss;
1904 for (
auto& item : inputs)
1906 auto prop = item.second.Volume->GetProperty();
1910 auto& map = item.second.OpacityTablesMap;
1911 const auto numComp = map.size();
1912 ss <<
"uniform sampler2D " << ArrayBaseName(map[0]) <<
"[" << numComp <<
"];\n";
1915 ss <<
"float computeOpacity(vec4 scalar, const in sampler2D opacityTF)\n"
1917 " return texture2D(opacityTF, vec2(scalar.w, 0)).r;\n"
1926 std::ostringstream ss;
1928 for (
auto& item : inputs)
1930 auto prop = item.second.Volume->GetProperty();
1934 auto& map = item.second.GradientOpacityTablesMap;
1935 const auto numComp = map.size();
1936 ss <<
"uniform sampler2D " << ArrayBaseName(map[0]) <<
"[" << numComp <<
"];\n";
1939 ss <<
"float computeGradientOpacity(vec4 grad, const in sampler2D gradientTF)\n"
1941 " return texture2D(gradientTF, vec2(grad.w, 0.0)).r;\n"
1949 int independentComponents, std::map<int, std::string> opacityTableMap)
1951 std::ostringstream ss;
1952 ss <<
"uniform sampler2D " << ArrayBaseName(opacityTableMap[0]) <<
"[" << noOfComponents
1956 if (noOfComponents > 1 && independentComponents)
1959 \nfloat computeOpacity(vec4 scalar, int component)\
1962 for (
int i = 0; i < noOfComponents; ++i)
1964 std::ostringstream toString;
1967 \n if (component == " +
1968 toString.str() +
")");
1972 \n return texture2D(" +
1973 opacityTableMap[i]);
1975 shaderStr +=
std::string(
",vec2(scalar[" + toString.str() +
"], 0)).r;\
1982 else if (noOfComponents == 2 && !independentComponents)
1985 \nfloat computeOpacity(vec4 scalar)\
1987 \n return texture2D(" +
1988 opacityTableMap[0] +
", vec2(scalar.y, 0)).r;\
1995 \nfloat computeOpacity(vec4 scalar)\
1997 \n return texture2D(" +
1998 opacityTableMap[0] +
", vec2(scalar.w, 0)).r;\
2006 int vtkNotUsed(independentComponents), std::map<int, std::string> colorTableMap)
2008 if (noOfComponents == 1)
2012 "vec4 computeColor(vec4 scalar, float opacity)\n"
2014 " vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
2015 " yscalar.r = yscalar.r * in_transfer2DYAxis_scale.r + in_transfer2DYAxis_bias.r;\n"
2016 " yscalar = vec4(yscalar.r);\n"
2017 " vec4 color = texture2D(" +
2020 " vec2(scalar.w, yscalar.w));\n"
2021 " return computeLighting(color, 0, 0);\n"
2024 return std::string(
"vec4 computeColor(vec4 scalar, float opacity)\n"
2026 " return vec4(0, 0, 0, 0)\n"
2033 int independentComponents, std::map<int, std::string> colorTableMap,
int useGradient)
2039 if (noOfComponents == 1)
2042 return std::string(
"vec4 computeColor(vec4 scalar, float opacity)\n"
2044 " vec4 color = texture2D(" +
2047 " vec2(scalar.w, g_gradients_0[0].w));\n"
2048 " return computeLighting(color, 0, 0);\n"
2051 else if (noOfComponents > 1 && independentComponents)
2055 shaderStr +=
std::string(
"vec4 computeColor(vec4 scalar, float opacity, int component)\n"
2058 for (
int i = 0; i < noOfComponents; ++i)
2060 std::ostringstream toString;
2063 shaderStr +=
std::string(
" if (component == " + num +
2066 " vec4 color = texture2D(" +
2070 num +
"], g_gradients_0[" + num +
2072 " return computeLighting(color, " +
2081 else if (noOfComponents == 2 && !independentComponents)
2084 return std::string(
"vec4 computeColor(vec4 scalar, float opacity)\n"
2086 " vec4 color = texture2D(" +
2089 " vec2(scalar.x, g_gradients_0[0].w));\n"
2090 " return computeLighting(color, 0, 0.0);\n"
2095 return std::string(
"vec4 computeColor(vec4 scalar, float opacity)\n"
2097 " return computeLighting(vec4(scalar.xyz, opacity), 0, 0.0);\n"
2105 std::ostringstream ss;
2106 for (
auto& item : inputs)
2108 auto prop = item.second.Volume->GetProperty();
2112 auto& map = item.second.TransferFunctions2DMap;
2113 const auto numComp = map.size();
2114 ss <<
"uniform sampler2D " << ArrayBaseName(map[0]) <<
"[" << numComp <<
"];\n";
2118 std::string(
"uniform sampler3D in_transfer2DYAxis;\n"
2119 "uniform vec4 in_transfer2DYAxis_scale;\n"
2120 "uniform vec4 in_transfer2DYAxis_bias;\n");
2128 int independentComponents, std::map<int, std::string> opacityTableMap,
int useGradient)
2130 std::ostringstream toString;
2131 if (noOfComponents > 1 && independentComponents)
2134 toString <<
"float computeOpacity(vec4 scalar, int component)\n"
2139 <<
"vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
2140 "for (int i = 0; i < 4; ++i)\n"
2142 " yscalar[i] = yscalar[i] * in_transfer2DYAxis_scale[i] + in_transfer2DYAxis_bias[i];\n"
2144 if (noOfComponents == 1)
2146 toString <<
"yscalar = vec4(yscalar.r);\n";
2150 for (
int i = 0; i < noOfComponents; ++i)
2154 toString <<
" if (component == " << i
2157 " return texture2D("
2158 << opacityTableMap[i]
2161 << i <<
"], g_gradients_0[" << i
2167 toString <<
" if (component == " << i
2170 " return texture2D("
2171 << opacityTableMap[i]
2174 << i <<
"], yscalar[" << i
2183 else if (noOfComponents == 2 && !independentComponents)
2188 toString <<
"float computeOpacity(vec4 scalar)\n"
2190 " return texture2D(" +
2191 opacityTableMap[0] +
2193 " vec2(scalar.y, g_gradients_0[0].w)).a;\n"
2199 toString <<
"float computeOpacity(vec4 scalar)\n"
2201 " return texture2D(" +
2202 opacityTableMap[0] +
2204 " vec2(scalar.y, yscalar.y)).a;\n"
2214 toString <<
"float computeOpacity(vec4 scalar)\n"
2216 " return texture2D(" +
2217 opacityTableMap[0] +
2219 " vec2(scalar.a, g_gradients_0[0].w)).a;\n"
2226 <<
"float computeOpacity(vec4 scalar)\n"
2228 " vec4 yscalar = texture3D(in_transfer2DYAxis, g_dataPos);\n"
2229 " yscalar.r = yscalar.r * in_transfer2DYAxis_scale.r + in_transfer2DYAxis_bias.r;\n"
2230 " yscalar = vec4(yscalar.r);\n"
2231 " return texture2D(" +
2232 opacityTableMap[0] +
2234 " vec2(scalar.a, yscalar.w)).a;\n"
2238 return toString.str();
2243 vtkVolume* vtkNotUsed(vol),
int noOfComponents,
int independentComponents,
2252 const size_t numInputs = inputs.size();
2253 const bool hasGradOp = ::HasGradientOpacity(inputs);
2258 functionSignature =
"float volumeShadow(vec3 sample_position, vec3 light_pos_dir, float is_Pos, "
2259 " in int c, in sampler3D volume, " +
2261 (numInputs > 1 && hasGradOp ? std::string(
"in sampler2D gradTF, ") :
std::string()) +
2262 "int index, float label)\n";
2267 vec3 direction = vec3(0.0);
2268 vec3 norm_dir = vec3(0.0);
2269 float maxdist = 0.0;
2272 float opacity = 0.0;
2276 float sampled_dist = 0.0;
2277 vec3 sampled_point = vec3(0.0);
2282 // direction is light_pos_dir when light is directional
2283 // and light_pos_dir - sample_position when positional
2284 direction = light_pos_dir - is_Pos * sample_position;
2285 norm_dir = normalize(direction);
2286 // introduce little offset to avoid sampling shadows at the exact
2288 sample_position += g_lengthStep * norm_dir;
2289 direction = light_pos_dir - is_Pos * sample_position;
2290 ray.origin = sample_position;
2293 ray.invDir = 1.0/ray.dir;
2294 if(!BBoxIntersect(vec3(0.0), vec3(1.0), ray, hit))
2296 // it can happen around the bounding box
2299 if(hit.tmax < g_lengthStep)
2301 // if we're too close to the bounding box
2304 // in case of directional light, we want direction not to be normalized but to go
2305 // all the way to the bbox
2306 direction *= pow(hit.tmax / length(direction), 1.0 - is_Pos);
2307 maxdist = min(hit.tmax, length(direction));
2308 maxdist = min(in_giReach, maxdist);
2309 if(maxdist < EPSILON) return 1.0;
2315 opacityEval +=
" scalar = texture3D(volume, sampled_point)[c];\n"
2316 " scalar = scalar * in_volume_scale[index][c] + in_volume_bias[index][c];\n";
2318 mapper, inputs, noOfComponents, independentComponents, useGradYAxis,
"sampled_point",
true);
2320 resStr += functionSignature +
"{\n" + declarations + rayInit +
2322 float current_dist = 0.0;
2323 float current_step = g_lengthStep;
2324 float clamped_step = 0.0;
2325 while(current_dist < maxdist)
2327 clamped_step = min(maxdist - current_dist, current_step);
2328 sampled_dist = current_dist + clamped_step * g_jitterValue;
2329 sampled_point = sample_position + sampled_dist * norm_dir;
2333 shadow *= 1.0 - opacity;
2334 current_dist += current_step;
2357 \n bool l_firstValue;\
2358 \n vec4 l_maxValue;");
2363 \n bool l_firstValue;\
2364 \n vec4 l_minValue;");
2369 \n uvec4 l_numSamples;\
2370 \n vec4 l_avgValue;");
2375 \n vec4 l_sumValue;");
2380 \n int l_initialIndex = 0;\
2381 \n float l_normValues[NUMBER_OF_CONTOURS + 2];");
2396 \n // We get data between 0.0 - 1.0 range\
2397 \n l_firstValue = true;\
2398 \n l_maxValue = vec4(0.0);");
2403 \n //We get data between 0.0 - 1.0 range\
2404 \n l_firstValue = true;\
2405 \n l_minValue = vec4(1.0);");
2410 \n //We get data between 0.0 - 1.0 range\
2411 \n l_avgValue = vec4(0.0);\
2412 \n // Keep track of number of samples\
2413 \n l_numSamples = uvec4(0);");
2418 \n //We get data between 0.0 - 1.0 range\
2419 \n l_sumValue = vec4(0.0);");
2424 \n#if NUMBER_OF_CONTOURS\
2425 \n l_normValues[0] = -1e20; //-infinity\
2426 \n l_normValues[NUMBER_OF_CONTOURS+1] = +1e20; //+infinity\
2427 \n for (int i = 0; i < NUMBER_OF_CONTOURS; i++)\
2429 \n l_normValues[i+1] = (in_isosurfacesValues[i] - in_scalarsRange[0].x) / \
2430 \n (in_scalarsRange[0].y - in_scalarsRange[0].x);\
2445 const int numInputs =
static_cast<int>(inputs.size());
2446 const int comp = numInputs == 1 ?
2448 (!independentComponents ? 1 : numInputs)
2453 std::ostringstream toShader;
2454 for (
const auto& item : inputs)
2456 auto& input = item.second;
2457 if (input.Volume->GetProperty()->HasGradientOpacity())
2459 toShader <<
"vec4 " << input.GradientCacheName <<
"[" << comp <<
"];\n";
2463 return toShader.str();
2468 int noOfComponents = 1,
int independentComponents = 0)
2470 std::ostringstream shader;
2471 if (independentComponents)
2473 if (noOfComponents == 1)
2475 shader <<
"g_gradients_0[0] = computeGradient(g_dataPos, 0, in_volume[0], 0);\n";
2480 shader <<
"for (int comp = 0; comp < in_noOfComponents; comp++)\n"
2482 " g_gradients_0[comp] = computeGradient(g_dataPos, comp, in_volume[0], 0);\n"
2488 shader <<
"g_gradients_0[0] = computeGradient(g_dataPos, 0, in_volume[0], 0);\n";
2491 return shader.str();
2498 std::ostringstream toShaderStr;
2499 toShaderStr <<
" if (!g_skip)\n"
2509 for (
auto& item : inputs)
2511 auto& input = item.second;
2512 auto property = input.Volume->GetProperty();
2514 const auto idx = i + 1;
2519 " texPos = (in_cellToPoint[" << idx <<
"] * in_inverseTextureDatasetMatrix[" << idx
2520 <<
"] * in_inverseVolumeMatrix[" << idx
2522 " in_volumeMatrix[0] * in_textureDatasetMatrix[0] * "
2523 "vec4(g_dataPos.xyz, 1.0)).xyz;\n"
2524 " if ((all(lessThanEqual(texPos, vec3(1.0))) &&\n"
2525 " all(greaterThanEqual(texPos, vec3(0.0)))))\n"
2527 " vec4 scalar = texture3D(in_volume["
2530 " scalar = scalar * in_volume_scale["
2531 << i <<
"] + in_volume_bias[" << i <<
"];\n";
2534 if (property->GetIndependentComponents())
2536 toShaderStr <<
" scalar = vec4(scalar.r);\n";
2539 toShaderStr <<
" g_srcColor = vec4(0.0);\n";
2543 std::string gradientopacity_param = (
property->HasGradientOpacity())
2544 ? input.GradientOpacityTablesMap[0] +
std::string(
", ")
2547 toShaderStr <<
" g_srcColor.a = computeOpacity(scalar,"
2548 << input.OpacityTablesMap[0]
2550 " if (g_srcColor.a > 0.0)\n"
2552 " g_srcColor = computeColor(texPos, scalar, g_srcColor.a, "
2553 << input.RGBTablesMap[0] <<
", " << gradientopacity_param <<
"in_volume[" << i
2554 <<
"], " << input.OpacityTablesMap[0] <<
", " << i <<
");\n";
2556 if (property->HasGradientOpacity())
2558 const auto& grad = input.GradientCacheName;
2559 toShaderStr <<
" " << grad <<
"[0] = computeGradient(texPos, 0, "
2560 <<
"in_volume[" << i <<
"], " << i
2564 <<
"[0].w >= 0.0)\n"
2566 " g_srcColor.a *= computeGradientOpacity("
2567 << grad <<
"[0], " << input.GradientOpacityTablesMap[0]
2574 const auto& grad = input.GradientCacheName;
2577 " " << grad <<
"[0] = computeGradient(texPos, 0, "
2578 <<
"in_volume[" << i <<
"], " << i
2580 " g_srcColor = texture2D("
2581 << input.TransferFunctions2DMap[0] <<
", vec2(scalar.r, "
2582 << input.GradientCacheName
2584 " if (g_srcColor.a > 0.0)\n"
2589 <<
" g_srcColor.rgb *= g_srcColor.a;\n"
2590 " g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;\n"
2599 toShaderStr <<
" }\n";
2601 return toShaderStr.str();
2607 int noOfComponents,
int independentComponents = 0)
2621 \n // Compute IJK vertex position for current sample in the rectilinear grid\
2622 \n vec4 dataPosWorld = in_volumeMatrix[0] * in_textureDatasetMatrix[0] * vec4(g_dataPos, 1.0);\
2623 \n dataPosWorld = dataPosWorld / dataPosWorld.w;\
2624 \n dataPosWorld.w = 1.0;\
2625 \n ivec3 ijk = ivec3(0);\
2626 \n vec3 ijkTexCoord = vec3(0.0);\
2627 \n vec3 pCoords = vec3(0.0);\
2628 \n vec3 xPrev, xNext, tmp;\
2629 \n int sz = textureSize(in_coordTexs, 0);\
2630 \n vec4 dataPosWorldScaled = dataPosWorld * vec4(in_coordsScale, 1.0) +\
2631 \n vec4(in_coordsBias, 1.0);\
2632 \n for (int j = 0; j < 3; ++j)\
2634 \n xPrev = texture1D(in_coordTexs, 0.0).xyz;\
2635 \n xNext = texture1D(in_coordTexs, (in_coordTexSizes[j] - 1) / sz).xyz;\
2636 \n if (xNext[j] < xPrev[j])\
2642 \n for (int i = 0; i < int(in_coordTexSizes[j]); i++)\
2644 \n xNext = texture1D(in_coordTexs, (i + 0.5) / sz).xyz;\
2645 \n if (dataPosWorldScaled[j] >= xPrev[j] && dataPosWorldScaled[j] < xNext[j])\
2648 \n pCoords[j] = (dataPosWorldScaled[j] - xPrev[j]) / (xNext[j] - xPrev[j]);\
2651 \n else if (dataPosWorldScaled[j] == xNext[j])\
2654 \n pCoords[j] = 1.0;\
2659 \n ijkTexCoord[j] = (ijk[j] + pCoords[j]) / in_coordTexSizes[j];\
2661 \n scalar = texture3D(in_volume[0], sign(in_cellSpacing[0]) * ijkTexCoord);\
2667 \n scalar = texture3D(in_volume[0], g_dataPos);\
2672 if (noOfComponents == 1)
2675 \n scalar.r = scalar.r * in_volume_scale[0].r + in_volume_bias[0].r;\
2676 \n scalar = vec4(scalar.r);");
2682 \n scalar = scalar * in_volume_scale[0] + in_volume_bias[0];");
2687 if (noOfComponents > 1)
2689 if (!independentComponents)
2692 \n if (l_maxValue.w < scalar.w || l_firstValue)\
2694 \n l_maxValue = scalar;\
2697 \n if (l_firstValue)\
2699 \n l_firstValue = false;\
2705 \n for (int i = 0; i < in_noOfComponents; ++i)\
2707 \n if (l_maxValue[i] < scalar[i] || l_firstValue)\
2709 \n l_maxValue[i] = scalar[i];\
2712 \n if (l_firstValue)\
2714 \n l_firstValue = false;\
2721 \n if (l_maxValue.w < scalar.x || l_firstValue)\
2723 \n l_maxValue.w = scalar.x;\
2726 \n if (l_firstValue)\
2728 \n l_firstValue = false;\
2734 if (noOfComponents > 1)
2736 if (!independentComponents)
2739 \n if (l_minValue.w > scalar.w || l_firstValue)\
2741 \n l_minValue = scalar;\
2744 \n if (l_firstValue)\
2746 \n l_firstValue = false;\
2752 \n for (int i = 0; i < in_noOfComponents; ++i)\
2754 \n if (l_minValue[i] < scalar[i] || l_firstValue)\
2756 \n l_minValue[i] = scalar[i];\
2759 \n if (l_firstValue)\
2761 \n l_firstValue = false;\
2768 \n if (l_minValue.w > scalar.x || l_firstValue)\
2770 \n l_minValue.w = scalar.x;\
2773 \n if (l_firstValue)\
2775 \n l_firstValue = false;\
2781 if (noOfComponents > 1 && independentComponents)
2784 \n for (int i = 0; i < in_noOfComponents; ++i)\
2786 \n // Get the intensity in volume scalar range\
2787 \n float intensity = in_scalarsRange[i][0] +\
2788 \n (in_scalarsRange[i][1] -\
2789 \n in_scalarsRange[i][0]) * scalar[i];\
2790 \n if (in_averageIPRange.x <= intensity &&\
2791 \n intensity <= in_averageIPRange.y)\
2793 \n l_avgValue[i] += computeOpacity(scalar, i) * scalar[i];\
2794 \n ++l_numSamples[i];\
2801 \n // Get the intensity in volume scalar range\
2802 \n float intensity = in_scalarsRange[0][0] +\
2803 \n (in_scalarsRange[0][1] -\
2804 \n in_scalarsRange[0][0]) * scalar.x;\
2805 \n if (in_averageIPRange.x <= intensity &&\
2806 \n intensity <= in_averageIPRange.y)\
2808 \n l_avgValue.x += computeOpacity(scalar) * scalar.x;\
2809 \n ++l_numSamples.x;\
2815 if (noOfComponents > 1 && independentComponents)
2818 \n for (int i = 0; i < in_noOfComponents; ++i)\
2820 \n float opacity = computeOpacity(scalar, i);\
2821 \n l_sumValue[i] = l_sumValue[i] + opacity * scalar[i];\
2827 \n float opacity = computeOpacity(scalar);\
2828 \n l_sumValue.x = l_sumValue.x + opacity * scalar.x;");
2834 \n#if NUMBER_OF_CONTOURS\
2835 \n int maxComp = 0;");
2838 if (noOfComponents > 1 && independentComponents)
2841 \n for (int i = 1; i < in_noOfComponents; ++i)\
2843 \n if (in_componentWeight[i] > in_componentWeight[maxComp])\
2846 compParamStr =
", maxComp";
2849 \n if (g_currentT == 0)\
2851 \n l_initialIndex = findIsoSurfaceIndex(scalar[maxComp], l_normValues);\
2856 \n bool shade = false;\
2857 \n l_initialIndex = clamp(l_initialIndex, 0, NUMBER_OF_CONTOURS);\
2858 \n if (scalar[maxComp] < l_normValues[l_initialIndex])\
2860 \n s = l_normValues[l_initialIndex];\
2861 \n l_initialIndex--;\
2864 \n if (scalar[maxComp] > l_normValues[l_initialIndex+1])\
2866 \n s = l_normValues[l_initialIndex+1];\
2867 \n l_initialIndex++;\
2870 \n if (shade == true)\
2872 \n vec4 vs = vec4(s);\
2873 \n g_srcColor.a = computeOpacity(vs " +
2875 \n g_srcColor = computeColor(vs, g_srcColor.a " +
2877 \n g_srcColor.rgb *= g_srcColor.a;\
2878 \n g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;\
2886 \n // test if the intersection is inside the volume bounds\
2887 \n if (any(greaterThan(g_dataPos, vec3(1.0))) || any(lessThan(g_dataPos, vec3(0.0))))\
2891 \n float opacity = computeOpacity(scalar);\
2892 \n g_fragColor = computeColor(scalar, opacity);\
2893 \n g_fragColor.rgb *= opacity;\
2894 \n g_exit = true;");
2898 if (noOfComponents > 1 && independentComponents)
2901 \n vec4 color[4]; vec4 tmp = vec4(0.0);\
2902 \n float totalAlpha = 0.0;\
2903 \n for (int i = 0; i < in_noOfComponents; ++i)\
2906 if (glMapper->GetUseDepthPass() &&
2910 \n // Data fetching from the red channel of volume texture\
2911 \n float opacity = computeOpacity(scalar, i);\
2912 \n if (opacity > 0.0)\
2914 \n g_srcColor.a = opacity;\
2921 \n // Data fetching from the red channel of volume texture\
2922 \n color[i][3] = computeOpacity(scalar, i);\
2923 \n color[i] = computeColor(scalar, color[i][3], i);\
2924 \n totalAlpha += color[i][3] * in_componentWeight[i];\
2926 \n if (totalAlpha > 0.0)\
2928 \n for (int i = 0; i < in_noOfComponents; ++i)\
2930 \n // Only let visible components contribute to the final color\
2931 \n if (in_componentWeight[i] <= 0) continue;\
2933 \n tmp.x += color[i].x * color[i].w * in_componentWeight[i];\
2934 \n tmp.y += color[i].y * color[i].w * in_componentWeight[i];\
2935 \n tmp.z += color[i].z * color[i].w * in_componentWeight[i];\
2936 \n tmp.w += ((color[i].w * color[i].w)/totalAlpha);\
2939 \n g_fragColor = (1.0f - g_fragColor.a) * tmp + g_fragColor;");
2942 else if (glMapper->GetUseDepthPass() &&
2946 \n g_srcColor = vec4(0.0);\
2947 \n g_srcColor.a = computeOpacity(scalar);");
2954 \n g_srcColor = vec4(0.0);\
2955 \n g_srcColor.a = computeOpacity(scalar);\
2956 \n if (g_srcColor.a > 0.0)\
2958 \n g_srcColor = computeColor(scalar, g_srcColor.a);");
2962 \n // Opacity calculation using compositing:\
2963 \n // Here we use front to back compositing scheme whereby\
2964 \n // the current sample value is multiplied to the\
2965 \n // currently accumulated alpha and then this product\
2966 \n // is subtracted from the sample value to get the\
2967 \n // alpha from the previous steps. Next, this alpha is\
2968 \n // multiplied with the current sample colour\
2969 \n // and accumulated to the composited colour. The alpha\
2970 \n // value from the previous steps is then accumulated\
2971 \n // to the composited colour alpha.\
2972 \n g_srcColor.rgb *= g_srcColor.a;\
2973 \n g_fragColor = (1.0f - g_fragColor.a) * g_srcColor + g_fragColor;");
2997 \n // Special coloring mode which renders the Prop Id in fragments that\
2998 \n // have accumulated certain level of opacity. Used during the selection\
2999 \n // pass vtkHardwareSelection::ACTOR_PASS.\
3000 \n if (g_fragColor.a > 3.0/ 255.0)\
3002 \n gl_FragData[0] = vec4(in_propId, 1.0);\
3006 \n gl_FragData[0] = vec4(0.0);\
3016 \n // Special coloring mode which renders the voxel index in fragments that\
3017 \n // have accumulated certain level of opacity. Used during the selection\
3018 \n // pass vtkHardwareSelection::ID_LOW24.\
3019 \n if (g_fragColor.a > 3.0/ 255.0)\
3021 \n uvec3 volumeDim = uvec3(in_textureExtentsMax - in_textureExtentsMin);\
3022 \n uvec3 voxelCoords = uvec3(volumeDim * g_dataPos);\
3023 \n // vtkHardwareSelector assumes index 0 to be empty space, so add uint(1).\
3024 \n uint idx = volumeDim.x * volumeDim.y * voxelCoords.z +\
3025 \n volumeDim.x * voxelCoords.y + voxelCoords.x + uint(1);\
3026 \n gl_FragData[0] = vec4(float(idx % uint(256)) / 255.0,\
3027 \n float((idx / uint(256)) % uint(256)) / 255.0,\
3028 \n float((idx / uint(65536)) % uint(256)) / 255.0, 1.0);\
3032 \n gl_FragData[0] = vec4(0.0);\
3042 \n // Special coloring mode which renders the voxel index in fragments that\
3043 \n // have accumulated certain level of opacity. Used during the selection\
3044 \n // pass vtkHardwareSelection::ID_MID24.\
3045 \n if (g_fragColor.a > 3.0/ 255.0)\
3047 \n uvec3 volumeDim = uvec3(in_textureExtentsMax - in_textureExtentsMin);\
3048 \n uvec3 voxelCoords = uvec3(volumeDim * g_dataPos);\
3049 \n // vtkHardwareSelector assumes index 0 to be empty space, so add uint(1).\
3050 \n uint idx = volumeDim.x * volumeDim.y * voxelCoords.z +\
3051 \n volumeDim.x * voxelCoords.y + voxelCoords.x + uint(1);\
3052 \n idx = ((idx & 0xff000000) >> 24);\
3053 \n gl_FragData[0] = vec4(float(idx % uint(256)) / 255.0,\
3054 \n float((idx / uint(256)) % uint(256)) / 255.0,\
3055 \n float(idx / uint(65536)) / 255.0, 1.0);\
3059 \n gl_FragData[0] = vec4(0.0);\
3066 vtkVolume* vtkNotUsed(vol),
int noOfComponents,
int independentComponents = 0)
3078 if (noOfComponents > 1 && independentComponents)
3081 \n g_srcColor = vec4(0);\
3082 \n for (int i = 0; i < in_noOfComponents; ++i)\
3084 \n vec4 tmp = computeColor(l_maxValue, computeOpacity(l_maxValue, i), i);\
3085 \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
3086 \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
3087 \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
3088 \n g_srcColor[3] += tmp[3] * in_componentWeight[i];\
3090 \n g_fragColor = g_srcColor;");
3095 \n g_srcColor = computeColor(l_maxValue,\
3096 \n computeOpacity(l_maxValue));\
3097 \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
3098 \n g_fragColor.a = g_srcColor.a;");
3103 if (noOfComponents > 1 && independentComponents)
3106 \n g_srcColor = vec4(0);\
3107 \n for (int i = 0; i < in_noOfComponents; ++i)\
3109 \n vec4 tmp = computeColor(l_minValue, computeOpacity(l_minValue, i), i);\
3110 \n g_srcColor[0] += tmp[0] * tmp[3] * in_componentWeight[i];\
3111 \n g_srcColor[1] += tmp[1] * tmp[3] * in_componentWeight[i];\
3112 \n g_srcColor[2] += tmp[2] * tmp[3] * in_componentWeight[i];\
3113 \n g_srcColor[2] += tmp[3] * tmp[3] * in_componentWeight[i];\
3115 \n g_fragColor = g_srcColor;");
3120 \n g_srcColor = computeColor(l_minValue,\
3121 \n computeOpacity(l_minValue));\
3122 \n g_fragColor.rgb = g_srcColor.rgb * g_srcColor.a;\
3123 \n g_fragColor.a = g_srcColor.a;");
3128 if (noOfComponents > 1 && independentComponents)
3131 \n for (int i = 0; i < in_noOfComponents; ++i)\
3133 \n if (l_numSamples[i] == uint(0))\
3137 \n l_avgValue[i] = l_avgValue[i] * in_componentWeight[i] /\
3138 \n l_numSamples[i];\
3141 \n l_avgValue[0] += l_avgValue[i];\
3144 \n l_avgValue[0] = clamp(l_avgValue[0], 0.0, 1.0);\
3145 \n g_fragColor = vec4(vec3(l_avgValue[0]), 1.0);");
3150 \n if (l_numSamples.x == uint(0))\
3156 \n l_avgValue.x /= l_numSamples.x;\
3157 \n l_avgValue.x = clamp(l_avgValue.x, 0.0, 1.0);\
3158 \n g_fragColor = vec4(vec3(l_avgValue.x), 1.0);\
3164 if (noOfComponents > 1 && independentComponents)
3168 \n l_sumValue.x *= in_componentWeight.x;\
3169 \n for (int i = 1; i < in_noOfComponents; ++i)\
3171 \n l_sumValue.x += l_sumValue[i] * in_componentWeight[i];\
3173 \n l_sumValue.x = clamp(l_sumValue.x, 0.0, 1.0);\
3174 \n g_fragColor = vec4(vec3(l_sumValue.x), 1.0);");
3179 \n l_sumValue.x = clamp(l_sumValue.x, 0.0, 1.0);\
3180 \n g_fragColor = vec4(vec3(l_sumValue.x), 1.0);");
3201 \n const float g_opacityThreshold = 1.0 - 1.0 / 255.0;");
3209 \n uniform vec3 in_propId;");
3218 \n // Flag to indicate if the raymarch loop should terminate \
3219 \n bool stop = false;\
3221 \n g_terminatePointMax = 0.0;\
3223 \n vec4 l_depthValue = texture2D(in_depthSampler, fragTexCoord);\
3225 \n if(gl_FragCoord.z >= l_depthValue.x)\
3230 \n // color buffer or max scalar buffer have a reduced size.\
3231 \n fragTexCoord = (gl_FragCoord.xy - in_windowLowerLeftCorner) *\
3232 \n in_inverseOriginalWindowSize;\
3240 if (sliceFunc->
IsA(
"vtkPlane"))
3244 \n // Intersection with plane\
3245 \n float t = intersectRayPlane(ip_vertexPos, rayDir);\
3246 \n vec4 intersection = vec4(ip_vertexPos + t * rayDir, 1.0);\
3247 \n g_intersection = (in_inverseTextureDatasetMatrix[0] * intersection).xyz;\
3248 \n vec4 intersDC = in_projectionMatrix * in_modelViewMatrix * in_volumeMatrix[0] * intersection;\
3249 \n intersDC.xyz /= intersDC.w;\
3250 \n vec4 intersWin = NDCToWindow(intersDC.x, intersDC.y, intersDC.z);\
3251 \n if(intersWin.z >= l_depthValue.x)\
3259 vtkErrorWithObjectMacro(
3260 sliceFunc,
"Implicit function type is not supported by this mapper.");
3266 \n // Compute max number of iterations it will take before we hit\
3267 \n // the termination point\
3269 \n // Abscissa of the point on the depth buffer along the ray.\
3270 \n // point in texture coordinates\
3271 \n vec4 rayTermination = WindowToNDC(gl_FragCoord.x, gl_FragCoord.y, l_depthValue.x);\
3273 \n // From normalized device coordinates to eye coordinates.\
3274 \n // in_projectionMatrix is inversed because of way VT\
3275 \n // From eye coordinates to texture coordinates\
3276 \n rayTermination = ip_inverseTextureDataAdjusted *\
3277 \n in_inverseVolumeMatrix[0] *\
3278 \n in_inverseModelViewMatrix *\
3279 \n in_inverseProjectionMatrix *\
3281 \n g_rayTermination = rayTermination.xyz / rayTermination.w;\
3283 \n // Setup the current segment:\
3284 \n g_dataPos = g_rayOrigin;\
3285 \n g_terminatePos = g_rayTermination;\
3287 \n g_terminatePointMax = length(g_terminatePos.xyz - g_dataPos.xyz) /\
3288 \n length(g_dirStep);\
3289 \n g_currentT = 0.0;");
3299 \n if(any(greaterThan(max(g_dirStep, vec3(0.0))*(g_dataPos - in_texMax[0]),vec3(0.0))) ||\
3300 \n any(greaterThan(min(g_dirStep, vec3(0.0))*(g_dataPos - in_texMin[0]),vec3(0.0))))\
3305 \n // Early ray termination\
3306 \n // if the currently composited colour alpha is already fully saturated\
3307 \n // we terminated the loop or if we have hit an obstacle in the\
3308 \n // direction of they ray (using depth buffer) we terminate as well.\
3309 \n if((g_fragColor.a > g_opacityThreshold) || \
3310 \n g_currentT >= g_terminatePointMax)\
3341 \nuniform float in_croppingPlanes[6];\
3342 \nuniform int in_croppingFlags [32];\
3343 \nfloat croppingPlanesTexture[6];\
3345 \n// X: axis = 0, Y: axis = 1, Z: axis = 2\
3346 \n// cp Cropping plane bounds (minX, maxX, minY, maxY, minZ, maxZ)\
3347 \nint computeRegionCoord(float cp[6], vec3 pos, int axis)\
3349 \n int cpmin = axis * 2;\
3350 \n int cpmax = cpmin + 1;\
3352 \n if (pos[axis] < cp[cpmin])\
3356 \n else if (pos[axis] >= cp[cpmin] &&\
3357 \n pos[axis] < cp[cpmax])\
3361 \n else if (pos[axis] >= cp[cpmax])\
3368 \nint computeRegion(float cp[6], vec3 pos)\
3370 \n return (computeRegionCoord(cp, pos, 0) +\
3371 \n (computeRegionCoord(cp, pos, 1) - 1) * 3 +\
3372 \n (computeRegionCoord(cp, pos, 2) - 1) * 9);\
3386 \n // Convert cropping region to texture space\
3387 \n mat4 datasetToTextureMat = in_inverseTextureDatasetMatrix[0];\
3389 \n vec4 tempCrop = vec4(in_croppingPlanes[0], 0.0, 0.0, 1.0);\
3390 \n tempCrop = datasetToTextureMat * tempCrop;\
3391 \n if (tempCrop[3] != 0.0)\
3393 \n tempCrop[0] /= tempCrop[3];\
3395 \n croppingPlanesTexture[0] = tempCrop[0];\
3397 \n tempCrop = vec4(in_croppingPlanes[1], 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[1] = tempCrop[0];\
3405 \n tempCrop = vec4(0.0, in_croppingPlanes[2], 0.0, 1.0);\
3406 \n tempCrop = datasetToTextureMat * tempCrop;\
3407 \n if (tempCrop[3] != 0.0)\
3409 \n tempCrop[1] /= tempCrop[3];\
3411 \n croppingPlanesTexture[2] = tempCrop[1];\
3413 \n tempCrop = vec4(0.0, in_croppingPlanes[3], 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[3] = tempCrop[1];\
3421 \n tempCrop = vec4(0.0, 0.0, in_croppingPlanes[4], 1.0);\
3422 \n tempCrop = datasetToTextureMat * tempCrop;\
3423 \n if (tempCrop[3] != 0.0)\
3425 \n tempCrop[2] /= tempCrop[3];\
3427 \n croppingPlanesTexture[4] = tempCrop[2];\
3429 \n tempCrop = vec4(0.0, 0.0, in_croppingPlanes[5], 1.0);\
3430 \n tempCrop = datasetToTextureMat * tempCrop;\
3431 \n if (tempCrop[3] != 0.0)\
3433 \n tempCrop[2] /= tempCrop[3];\
3435 \n croppingPlanesTexture[5] = tempCrop[2];");
3448 \n // Determine region\
3449 \n int regionNo = computeRegion(croppingPlanesTexture, g_dataPos);\
3451 \n // Do & operation with cropping flags\
3452 \n // Pass the flag that its Ok to sample or not to sample\
3453 \n if (in_croppingFlags[regionNo] == 0)\
3455 \n // Skip this voxel\
3484 \n /// We support only 8 clipping planes for now\
3485 \n /// The first value is the size of the data array for clipping\
3486 \n /// planes (origin, normal)\
3487 \n uniform float in_clippingPlanes[49];\
3488 \n uniform float in_clippedVoxelIntensity;\
3490 \n int clip_numPlanes;\
3491 \n vec3 clip_rayDirObj;\
3492 \n mat4 clip_texToObjMat;\
3493 \n mat4 clip_objToTexMat;\
3495 \n// Tighten the sample range as needed to account for clip planes. \
3496 \n// Arguments are in texture coordinates. \
3497 \n// Returns true if the range is at all valid after clipping. If not, \
3498 \n// the fragment should be discarded. \
3499 \nbool AdjustSampleRangeForClipping(inout vec3 startPosTex, inout vec3 stopPosTex) \
3501 \n vec4 startPosObj = vec4(0.0);\
3503 \n startPosObj = clip_texToObjMat * vec4(startPosTex - g_rayJitter, 1.0);\
3504 \n startPosObj = startPosObj / startPosObj.w;\
3505 \n startPosObj.w = 1.0;\
3508 \n vec4 stopPosObj = vec4(0.0);\
3510 \n stopPosObj = clip_texToObjMat * vec4(stopPosTex, 1.0);\
3511 \n stopPosObj = stopPosObj / stopPosObj.w;\
3512 \n stopPosObj.w = 1.0;\
3515 \n for (int i = 0; i < clip_numPlanes; i = i + 6)\
3517 \n vec3 planeOrigin = vec3(in_clippingPlanes[i + 1],\
3518 \n in_clippingPlanes[i + 2],\
3519 \n in_clippingPlanes[i + 3]);\
3520 \n vec3 planeNormal = normalize(vec3(in_clippingPlanes[i + 4],\
3521 \n in_clippingPlanes[i + 5],\
3522 \n in_clippingPlanes[i + 6]));\
3524 \n // Abort if the entire segment is clipped:\
3525 \n // (We can do this before adjusting the term point, since it'll \
3526 \n // only move further into the clipped area)\
3527 \n float startDistance = dot(planeNormal, planeOrigin - startPosObj.xyz);\
3528 \n float stopDistance = dot(planeNormal, planeOrigin - stopPosObj.xyz);\
3529 \n bool startClipped = startDistance > 0.0;\
3530 \n bool stopClipped = stopDistance > 0.0;\
3531 \n if (startClipped && stopClipped)\
3536 \n float rayDotNormal = dot(clip_rayDirObj, planeNormal);\
3537 \n bool frontFace = rayDotNormal > 0.0;\
3539 \n // Move the start position further from the eye if needed:\
3540 \n if (frontFace && // Observing from the clipped side (plane's front face)\
3541 \n startDistance > 0.0) // Ray-entry lies on the clipped side.\
3543 \n // Scale the point-plane distance to the ray direction and update the\
3545 \n float rayScaledDist = startDistance / rayDotNormal;\
3546 \n startPosObj = vec4(startPosObj.xyz + rayScaledDist * clip_rayDirObj, 1.0);\
3547 \n vec4 newStartPosTex = clip_objToTexMat * vec4(startPosObj.xyz, 1.0);\
3548 \n newStartPosTex /= newStartPosTex.w;\
3549 \n startPosTex = newStartPosTex.xyz;\
3550 \n startPosTex += g_rayJitter;\
3553 \n // Move the end position closer to the eye if needed:\
3554 \n if (!frontFace && // Observing from the unclipped side (plane's back face)\
3555 \n stopDistance > 0.0) // Ray-entry lies on the unclipped side.\
3557 \n // Scale the point-plane distance to the ray direction and update the\
3558 \n // termination point.\
3559 \n float rayScaledDist = stopDistance / rayDotNormal;\
3560 \n stopPosObj = vec4(stopPosObj.xyz + rayScaledDist * clip_rayDirObj, 1.0);\
3561 \n vec4 newStopPosTex = clip_objToTexMat * vec4(stopPosObj.xyz, 1.0);\
3562 \n newStopPosTex /= newStopPosTex.w;\
3563 \n stopPosTex = newStopPosTex.xyz;\
3567 \n if (any(greaterThan(startPosTex, in_texMax[0])) ||\
3568 \n any(lessThan(startPosTex, in_texMin[0])))\
3591 \n vec4 tempClip = in_volumeMatrix[0] * vec4(rayDir, 0.0);\
3592 \n if (tempClip.w != 0.0)\
3594 \n tempClip = tempClip/tempClip.w;\
3595 \n tempClip.w = 1.0;\
3597 \n clip_rayDirObj = normalize(tempClip.xyz);");
3602 clip_rayDirObj = normalize(in_projectionDirection);");
3606 \n clip_numPlanes = int(in_clippingPlanes[0]);\
3607 \n clip_texToObjMat = in_volumeMatrix[0] * inverse(ip_inverseTextureDataAdjusted);\
3608 \n clip_objToTexMat = ip_inverseTextureDataAdjusted * in_inverseVolumeMatrix[0];\
3610 \n // Adjust for clipping.\
3611 \n if (!AdjustSampleRangeForClipping(g_rayOrigin, g_rayTermination))\
3612 \n { // entire ray is clipped.\
3616 \n // Update the segment post-clip:\
3617 \n g_dataPos = g_rayOrigin;\
3618 \n g_terminatePos = g_rayTermination;\
3619 \n g_terminatePointMax = length(g_terminatePos.xyz - g_dataPos.xyz) /\
3620 \n length(g_dirStep);\
3645 if (!mask || !maskInput)
3667 \nvec4 maskValue = texture3D(in_mask, g_dataPos);\
3668 \nif(maskValue.r <= 0.0)\
3687 \nuniform float in_maskBlendFactor;\
3688 \nuniform sampler2D in_labelMapTransfer;\
3689 \nuniform float in_mask_scale;\
3690 \nuniform float in_mask_bias;\
3691 \nuniform int in_labelMapNumLabels;\
3708 \nvec4 scalar = texture3D(in_volume[0], g_dataPos);");
3711 if (noOfComponents == 1)
3714 \n scalar.r = scalar.r * in_volume_scale[0].r + in_volume_bias[0].r;\
3715 \n scalar = vec4(scalar.r);");
3721 \n scalar = scalar * in_volume_scale[0] + in_volume_bias[0];");
3728 \nif (in_maskBlendFactor == 0.0)\
3730 \n g_srcColor.a = computeOpacity(scalar);\
3731 \n if (g_srcColor.a > 0)\
3733 \n g_srcColor = computeColor(scalar, g_srcColor.a);\
3738 \n float opacity = computeOpacity(scalar);\
3739 \n // Get the mask value at this same location\
3740 \n vec4 maskValue = texture3D(in_mask, g_dataPos);\
3741 \n maskValue.r = maskValue.r * in_mask_scale + in_mask_bias;\
3742 \n // Quantize the height of the labelmap texture over number of labels\
3743 \n if (in_labelMapNumLabels > 0)\
3746 \n floor(maskValue.r * in_labelMapNumLabels) /\
3747 \n in_labelMapNumLabels;\
3751 \n maskValue.r = 0.0;\
3753 \n if(maskValue.r == 0.0)\
3755 \n g_srcColor.a = opacity;\
3756 \n if (g_srcColor.a > 0)\
3758 \n g_srcColor = computeColor(scalar, g_srcColor.a);\
3763 \n g_srcColor = texture2D(in_labelMapTransfer,\
3764 \n vec2(scalar.r, maskValue.r));\
3765 \n if (g_srcColor.a > 0)\
3767 \n g_srcColor = computeLighting(g_srcColor, 0, maskValue.r);\
3769 \n if (in_maskBlendFactor < 1.0)\
3771 \n vec4 color = opacity > 0 ? computeColor(scalar, opacity) : vec4(0);\
3772 \n g_srcColor = (1.0 - in_maskBlendFactor) * color +\
3773 \n in_maskBlendFactor * g_srcColor;\
3784 return std::string(
"uniform bool in_clampDepthToBackface;\n"
3785 "vec3 l_opaqueFragPos;\n"
3786 "bool l_updateDepth;\n");
3794 \n l_opaqueFragPos = vec3(-1.0);\
3795 \n if(in_clampDepthToBackface)\
3797 \n l_opaqueFragPos = g_dataPos;\
3799 \n l_updateDepth = true;");
3807 \n if(!g_skip && g_srcColor.a > 0.0 && l_updateDepth)\
3809 \n l_opaqueFragPos = g_dataPos;\
3810 \n l_updateDepth = false;\
3819 \n if (l_opaqueFragPos == vec3(-1.0))\
3821 \n gl_FragData[1] = vec4(1.0);\
3825 \n vec4 depthValue = in_projectionMatrix * in_modelViewMatrix *\
3826 \n in_volumeMatrix[0] * in_textureDatasetMatrix[0] *\
3827 \n vec4(l_opaqueFragPos, 1.0);\
3828 \n depthValue /= depthValue.w;\
3829 \n gl_FragData[1] = vec4(vec3(0.5 * (gl_DepthRange.far -\
3830 \n gl_DepthRange.near) * depthValue.z + 0.5 *\
3831 \n (gl_DepthRange.far + gl_DepthRange.near)), 1.0);\
3840 \n vec3 l_isoPos = g_dataPos;");
3848 \n if(!g_skip && g_srcColor.a > 0.0)\
3850 \n l_isoPos = g_dataPos;\
3851 \n g_exit = true; g_skip = true;\
3860 \n vec4 depthValue = in_projectionMatrix * in_modelViewMatrix *\
3861 \n in_volumeMatrix[0] * in_textureDatasetMatrix[0] *\
3862 \n vec4(l_isoPos, 1.0);\
3863 \n gl_FragData[0] = vec4(l_isoPos, 1.0);\
3864 \n gl_FragData[1] = vec4(vec3((depthValue.z/depthValue.w) * 0.5 + 0.5),\
3873 \n initializeRayCast();\
3874 \n castRay(-1.0, -1.0);\
3875 \n finalizeRayCast();");
3880 const std::vector<std::string>& varNames,
size_t usedNames)
3883 for (
size_t i = 0; i < usedNames; i++)
3885 shader +=
"uniform sampler2D " + varNames[i] +
";\n";
3892 const std::vector<std::string>& varNames,
size_t usedNames)
3895 for (
size_t i = 0; i < usedNames; i++)
3897 std::stringstream ss;
3899 shader +=
" gl_FragData[" + ss.str() +
"] = texture2D(" + varNames[i] +
", texCoord);\n";
3901 shader +=
" return;\n";
3904 VTK_ABI_NAMESPACE_END
3907 #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
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 ImageSampleDeclarationFrag(const std::vector< std::string > &varNames, size_t usedNames)
static vtkGPUVolumeRayCastMapper * SafeDownCast(vtkObjectBase *o)
std::string WorkerImplementation(vtkRenderer *vtkNotUsed(ren), vtkVolumeMapper *vtkNotUsed(mapper), vtkVolume *vtkNotUsed(vol))
static vtkDataSet * SafeDownCast(vtkObjectBase *o)
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...
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))