vtkVolumeShaderComposer.h 66.2 KB
Newer Older
1 2 3
/*=========================================================================

  Program:   Visualization Toolkit
Aashish Chaudhary's avatar
Aashish Chaudhary committed
4
  Module:    vtkVolumeShaderComposer.h
5 6 7 8 9 10 11 12 13 14 15

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

16 17
#ifndef vtkVolumeShaderComposer_h
#define vtkVolumeShaderComposer_h
18 19 20 21 22 23 24 25 26

#include "vtkVolumeMask.h"

#include <vtkCamera.h>
#include <vtkRenderer.h>
#include <vtkVolume.h>
#include <vtkVolumeMapper.h>
#include <vtkVolumeProperty.h>

Aashish Chaudhary's avatar
Aashish Chaudhary committed
27
#include <map>
28
#include <sstream>
29 30 31 32 33 34 35 36
#include <string>

namespace vtkvolume
{
  //--------------------------------------------------------------------------
  std::string replace(std::string source, const std::string &search,
                      const std::string replace, bool all)
    {
37 38 39 40 41
    if (replace.empty())
      {
      return source;
      }

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
    std::string::size_type pos = 0;
    bool first = true;
    while ((pos = source.find(search, 0)) != std::string::npos)
      {
      source.replace(pos, search.length(), replace);
      pos += search.length();
      if (first)
        {
        first = false;
        if (!all)
          {
          return source;
          }
        }
      }
    return source;
    }

  //--------------------------------------------------------------------------
61 62 63
  std::string ComputeClipPositionImplementation(vtkRenderer* vtkNotUsed(ren),
                                                vtkVolumeMapper* vtkNotUsed(mapper),
                                                vtkVolume* vtkNotUsed(vol))
64
    {
65 66 67 68
    return std::string("\
      \n  vec4 pos = in_projectionMatrix * in_modelViewMatrix *\
      \n             in_volumeMatrix * vec4(in_vertexPos.xyz, 1.0);\
      \n  gl_Position = pos;"
69 70 71 72
    );
    }

  //--------------------------------------------------------------------------
73 74 75
  std::string ComputeTextureCoordinates(vtkRenderer* vtkNotUsed(ren),
                                        vtkVolumeMapper* vtkNotUsed(mapper),
                                        vtkVolume* vtkNotUsed(vol))
76 77
    {
    return std::string(
Aashish Chaudhary's avatar
Aashish Chaudhary committed
78
      "\n  // For point dataset, we offset the texture coordinate\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
79
       \n  // to account for OpenGL treating voxel at the center of the cell.\
80
       \n  vec3 spacingSign = vec3(1.0);\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
81
       \n  if (in_cellSpacing.x < 0.0)\
82 83 84
       \n    {\
      \n     spacingSign.x = -1.0;\
       \n    }\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
85
       \n  if (in_cellSpacing.y < 0.0)\
86 87 88
       \n    {\
       \n     spacingSign.y = -1.0;\
       \n    }\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
89
       \n  if (in_cellSpacing.z < 0.0)\
90 91 92 93 94
       \n    {\
       \n     spacingSign.z = -1.0;\
       \n    }\
       \n  vec3 uvx = spacingSign * (in_vertexPos - in_volumeExtentsMin) /\
       \n               (in_volumeExtentsMax - in_volumeExtentsMin);\
95 96 97 98 99 100 101 102 103
       \n  if (in_cellFlag)\
       \n    {\
       \n    ip_textureCoords = uvx;\
       \n    }\
       \n  else\
       \n    {\
       \n    vec3 delta = in_textureExtentsMax - in_textureExtentsMin;\
       \n    ip_textureCoords = (uvx * (delta - vec3(1.0)) + vec3(0.5)) / delta;\
       \n    }"
104 105 106 107
    );
    }

  //--------------------------------------------------------------------------
108 109 110
  std::string BaseDeclarationVertex(vtkRenderer* vtkNotUsed(ren),
                                    vtkVolumeMapper* vtkNotUsed(mapper),
                                    vtkVolume* vtkNotUsed(vol))
111 112
    {
    return std::string("\
113 114
      \n  uniform bool in_cellFlag;\
      \n  uniform vec3 in_cellSpacing;\
115 116 117 118 119 120 121 122 123
      \n  uniform mat4 in_modelViewMatrix;\
      \n  uniform mat4 in_projectionMatrix;\
      \n  uniform mat4 in_volumeMatrix;\
      \n\
      \n  uniform vec3 in_volumeExtentsMin;\
      \n  uniform vec3 in_volumeExtentsMax;\
      \n\
      \n  uniform vec3 in_textureExtentsMax;\
      \n  uniform vec3 in_textureExtentsMin;"
124 125 126 127
    );
    }

  //--------------------------------------------------------------------------
128 129 130 131 132
  std::string BaseDeclarationFragment(vtkRenderer* vtkNotUsed(ren),
                                      vtkVolumeMapper* vtkNotUsed(mapper),
                                      vtkVolume* vtkNotUsed(vol),
                                      int vtkNotUsed(numberOfLights),
                                      int lightingComplexity,
133
                                      bool hasGradientOpacity,
134 135
                                      int noOfComponents,
                                      int independentComponents)
136
    {
137 138 139
    std::string shaderStr = std::string("\
      \n// Volume dataset\
      \nuniform sampler3D in_volume;\
140 141
      \nuniform int in_noOfComponents;\
      \nuniform int in_independentComponents;\
142
      \n\
143
      \nuniform sampler2D in_noiseSampler;\
144
      \n#ifndef GL_ES\
145
      \nuniform sampler2D in_depthSampler;\
146
      \n#endif\
147
      \n\
148 149
      \n// Camera position\
      \nuniform vec3 in_cameraPos;\
150
      \n\
151 152 153 154 155 156 157 158 159
      \n// view and model matrices\
      \nuniform mat4 in_volumeMatrix;\
      \nuniform mat4 in_inverseVolumeMatrix;\
      \nuniform mat4 in_projectionMatrix;\
      \nuniform mat4 in_inverseProjectionMatrix;\
      \nuniform mat4 in_modelViewMatrix;\
      \nuniform mat4 in_inverseModelViewMatrix;\
      \nuniform mat4 in_textureDatasetMatrix;\
      \nuniform mat4 in_inverseTextureDatasetMatrix;\
160
      \nuniform mat4 in_texureToEyeIt;\
161
      \n\
162 163
      \n// Ray step size\
      \nuniform vec3 in_cellStep;\
164
      \nuniform vec2 in_scalarsRange[4];\
165
      \nuniform vec3 in_cellSpacing;\
166
      \n\
167 168
      \n// Sample distance\
      \nuniform float in_sampleDistance;\
169
      \n\
170 171 172 173 174 175 176
      \n// Scales\
      \nuniform vec3 in_cellScale;\
      \nuniform vec2 in_windowLowerLeftCorner;\
      \nuniform vec2 in_inverseOriginalWindowSize;\
      \nuniform vec2 in_inverseWindowSize;\
      \nuniform vec3 in_textureExtentsMax;\
      \nuniform vec3 in_textureExtentsMin;\
177
      \n\
178 179 180 181 182
      \n// Material and lighting\
      \nuniform vec3 in_diffuse;\
      \nuniform vec3 in_ambient;\
      \nuniform vec3 in_specular;\
      \nuniform float in_shininess;\
183 184
      \n\
      \n// Others\
185
      \nuniform bool in_cellFlag;\
186
      \n uniform bool in_useJittering;\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
187
      ");
188

189
    if (hasGradientOpacity || lightingComplexity > 0)
190
      {
191
      shaderStr += std::string("\
192 193
        \nvec3 g_xvec;\
        \nvec3 g_yvec;\
194 195 196 197
        \nvec3 g_zvec;"
      );
      }

198
    if (lightingComplexity > 0 || hasGradientOpacity)
199 200 201
      {
      shaderStr += std::string("\
        \nuniform bool in_twoSidedLighting;\
202 203
        \nvec3 g_cellSpacing;\
        \nfloat g_avgSpacing;"
204
      );
205 206
      }

207
    if (lightingComplexity == 3)
208
      {
209
      shaderStr += std::string("\
210
        \nvec4 g_fragWorldPos;\
211 212 213 214 215 216 217 218 219 220
        \nuniform int in_numberOfLights;\
        \nuniform vec3 in_lightAmbientColor[6];\
        \nuniform vec3 in_lightDiffuseColor[6];\
        \nuniform vec3 in_lightSpecularColor[6];\
        \nuniform vec3 in_lightDirection[6];\
        \nuniform vec3 in_lightPosition[6];\
        \nuniform vec3 in_lightAttenuation[6];\
        \nuniform float in_lightConeAngle[6];\
        \nuniform float in_lightExponent[6];\
        \nuniform int in_lightPositional[6];\
221 222
      ");
      }
223
    else if (lightingComplexity == 2)
224
      {
225
      shaderStr += std::string("\
226
        \nvec4 g_fragWorldPos;\
227 228 229 230 231 232 233 234 235 236 237 238 239
        \nuniform int in_numberOfLights;\
        \nuniform vec3 in_lightAmbientColor[6];\
        \nuniform vec3 in_lightDiffuseColor[6];\
        \nuniform vec3 in_lightSpecularColor[6];\
        \nuniform vec3 in_lightDirection[6];\
      ");
      }
    else
      {
      shaderStr += std::string("\
        \nuniform vec3 in_lightAmbientColor[1];\
        \nuniform vec3 in_lightDiffuseColor[1];\
        \nuniform vec3 in_lightSpecularColor[1];\
240 241 242
        \nvec4 g_lightPosObj;\
        \nvec3 g_ldir;\
        \nvec3 g_vdir;\
243 244
        \nvec3 g_h;\
        \nvec3 g_aspect;"
245
      );
246 247
      }

248 249 250
    if (noOfComponents > 1 && independentComponents)
      {
      shaderStr += std::string("\
251
        \nuniform vec4 in_componentWeight;");
252 253
      }

254
    return shaderStr;
255 256 257 258 259
    }

  //--------------------------------------------------------------------------
  std::string BaseInit(vtkRenderer* vtkNotUsed(ren),
                       vtkVolumeMapper* vtkNotUsed(mapper),
260 261
                       vtkVolume* vol,
                       int lightingComplexity)
262
    {
263
    std::string shaderStr = std::string("\
264 265
      \n  // Get the 3D texture coordinates for lookup into the in_volume dataset\
      \n  g_dataPos = ip_textureCoords.xyz;\
266
      \n\
267 268 269 270 271 272 273 274 275
      \n  // Eye position in object space\
      \n  g_eyePosObj = (in_inverseVolumeMatrix * vec4(in_cameraPos, 1.0));\
      \n  if (g_eyePosObj.w != 0.0)\
      \n    {\
      \n    g_eyePosObj.x /= g_eyePosObj.w;\
      \n    g_eyePosObj.y /= g_eyePosObj.w;\
      \n    g_eyePosObj.z /= g_eyePosObj.w;\
      \n    g_eyePosObj.w = 1.0;\
      \n    }\
276
      \n\
277 278
      \n  // Getting the ray marching direction (in object space);\
      \n  vec3 rayDir = computeRayDirection();\
279
      \n\
280 281 282 283
      \n  // Multiply the raymarching direction with the step size to get the\
      \n  // sub-step size we need to take at each raymarching step\
      \n  g_dirStep = (in_inverseTextureDatasetMatrix *\
      \n              vec4(rayDir, 0.0)).xyz * in_sampleDistance;\
284
      \n\
285 286 287 288 289 290 291 292 293
      \n  float jitterValue = (texture2D(in_noiseSampler, g_dataPos.xy).x);\
      \n  if (in_useJittering)\
      \n    {\
      \n    g_dataPos += g_dirStep * jitterValue;\
      \n    }\
      \n  else\
      \n    {\
      \n    g_dataPos += g_dirStep;\
      \n    }\
294
      \n\
295 296
      \n  // Flag to deternmine if voxel should be considered for the rendering\
      \n  bool l_skip = false;");
297 298 299 300 301 302 303 304 305 306 307 308 309

    if (vol->GetProperty()->GetShade() && lightingComplexity == 1)
      {
        shaderStr += std::string("\
          \n  // Light position in object space\
          \n  g_lightPosObj = (in_inverseVolumeMatrix *\
          \n                      vec4(in_cameraPos, 1.0));\
          \n  if (g_lightPosObj.w != 0.0)\
          \n    {\
          \n    g_lightPosObj.x /= g_lightPosObj.w;\
          \n    g_lightPosObj.y /= g_lightPosObj.w;\
          \n    g_lightPosObj.z /= g_lightPosObj.w;\
          \n    g_lightPosObj.w = 1.0;\
310 311 312
          \n    }\
          \n  g_ldir = normalize(g_lightPosObj.xyz - ip_vertexPos);\
          \n  g_vdir = normalize(g_eyePosObj.xyz - ip_vertexPos);\
313
          \n  g_h = normalize(g_ldir + g_vdir);"
314 315
        );
      }
316 317
    if (vol->GetProperty()->GetShade() ||
        vol->GetProperty()->HasGradientOpacity())
318 319
      {
      shaderStr += std::string("\
320 321 322 323 324 325
        \n  g_cellSpacing = vec3(in_cellSpacing[0],\
        \n                       in_cellSpacing[1],\
        \n                       in_cellSpacing[2]);\
        \n  g_avgSpacing = (g_cellSpacing[0] +\
        \n                  g_cellSpacing[1] +\
        \n                  g_cellSpacing[2])/3.0;\
326 327 328 329
        \n  g_xvec = vec3(in_cellStep[0], 0.0, 0.0);\
        \n  g_yvec = vec3(0.0, in_cellStep[1], 0.0);\
        \n  g_zvec = vec3(0.0, 0.0, in_cellStep[2]);"
      );
330
      }
Aashish Chaudhary's avatar
Aashish Chaudhary committed
331 332 333 334 335 336 337 338 339 340 341

    if (vol->GetProperty()->HasGradientOpacity())
      {
      shaderStr += std::string("\
        \n  // Adjust the aspect\
        \n  g_aspect.x = g_cellSpacing[0] * 2.0 / g_avgSpacing;\
        \n  g_aspect.y = g_cellSpacing[1] * 2.0 / g_avgSpacing;\
        \n  g_aspect.z = g_cellSpacing[2] * 2.0 / g_avgSpacing;"
      );
      }

342
      return shaderStr;
343 344 345
    }

  //--------------------------------------------------------------------------
346 347 348
  std::string BaseImplementation(vtkRenderer* vtkNotUsed(ren),
                                 vtkVolumeMapper* vtkNotUsed(mapper),
                                 vtkVolume* vtkNotUsed(vol))
349
    {
350 351 352
    return std::string("\
      \n    l_skip = false;"
    );
353 354 355 356 357 358 359
    }

  //--------------------------------------------------------------------------
  std::string BaseExit(vtkRenderer* vtkNotUsed(ren),
                       vtkVolumeMapper* vtkNotUsed(mapper),
                       vtkVolume* vtkNotUsed(vol))
    {
Aashish Chaudhary's avatar
Aashish Chaudhary committed
360
    return std::string();
361 362 363
    }

  //--------------------------------------------------------------------------
364 365 366 367 368
  std::string ComputeGradientDeclaration(vtkRenderer* vtkNotUsed(ren),
                                         vtkVolumeMapper* vtkNotUsed(mapper),
                                         vtkVolume* vol,
                                         int noOfComponents,
                                         int independentComponents,
369 370
                                         std::map<int, std::string>
                                           gradientTableMap)
371
  {
372
    std::string shaderStr;
373
    if (noOfComponents == 1 && vol->GetProperty()->HasGradientOpacity())
374
      {
375
      shaderStr += std::string("\
376
        \nuniform sampler2D in_gradientTransferFunc;\
377 378
        \nfloat computeGradientOpacity(vec4 grad)\
        \n  {\
379
        \n  return texture2D("+gradientTableMap[0]+", vec2(grad.w, 0.0)).r;\
380 381 382
        \n  }"
      );
      }
383 384 385
    else if (noOfComponents > 1 && independentComponents &&
             vol->GetProperty()->HasGradientOpacity())
      {
386
      std::ostringstream toString;
387 388
      for (int i = 0; i < noOfComponents; ++i)
        {
389
        shaderStr += std::string("\n uniform sampler2D ") +
390 391 392
                     gradientTableMap[i] + std::string(";");
        }

393 394
      shaderStr += std::string("\
        \nfloat computeGradientOpacity(vec4 grad, int component)\
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
        \n  {");

      for (int i = 0; i < noOfComponents; ++i)
        {
        toString << i;
        shaderStr += std::string("\
          \n  if (component == " + toString.str() + ")");

        shaderStr += std::string("\
          \n    {\
          \n    return texture2D("+ gradientTableMap[i] + ", vec2(grad.w, 0.0)).r;\
          \n    }"
        );

        // Reset
        toString.str("");
        toString.clear();
        }

      shaderStr += std::string("\
        \n  }");
416
      }
417 418 419 420 421

    if (vol->GetProperty()->GetShade() &&
        !vol->GetProperty()->HasGradientOpacity())
      {
      shaderStr += std::string("\
422 423
        \n// c is short for component\
        \nvec4 computeGradient(int c)\
424 425 426
        \n  {\
        \n  vec3 g1;\
        \n  vec3 g2;\
427 428 429 430 431 432
        \n  g1.x = texture3D(in_volume, vec3(g_dataPos + g_xvec)).x;\
        \n  g1.y = texture3D(in_volume, vec3(g_dataPos + g_yvec)).x;\
        \n  g1.z = texture3D(in_volume, vec3(g_dataPos + g_zvec)).x;\
        \n  g2.x = texture3D(in_volume, vec3(g_dataPos - g_xvec)).x;\
        \n  g2.y = texture3D(in_volume, vec3(g_dataPos - g_yvec)).x;\
        \n  g2.z = texture3D(in_volume, vec3(g_dataPos - g_zvec)).x;\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
433 434
        \n  g1 = g1 * in_volume_scale.r + in_volume_bias.r;\
        \n  g2 = g2 * in_volume_scale.r + in_volume_bias.r;\
435
        \n  return vec4((g1 - g2), -1.0);\
436 437
        \n  }"
      );
438
    }
439
    else if (vol->GetProperty()->HasGradientOpacity())
440
      {
441
      shaderStr += std::string("\
442 443
        \n// c is short for component\
        \nvec4 computeGradient(int c)\
444 445 446
        \n  {\
        \n  vec3 g1;\
        \n  vec4 g2;\
447 448 449 450 451 452
        \n  g1.x = texture3D(in_volume, vec3(g_dataPos + g_xvec)).x;\
        \n  g1.y = texture3D(in_volume, vec3(g_dataPos + g_yvec)).x;\
        \n  g1.z = texture3D(in_volume, vec3(g_dataPos + g_zvec)).x;\
        \n  g2.x = texture3D(in_volume, vec3(g_dataPos - g_xvec)).x;\
        \n  g2.y = texture3D(in_volume, vec3(g_dataPos - g_yvec)).x;\
        \n  g2.z = texture3D(in_volume, vec3(g_dataPos - g_zvec)).x;\
453 454
        \n  g1 = g1 * in_volume_scale.r + in_volume_bias.r;\
        \n  g2 = g2 * in_volume_scale.r + in_volume_bias.r;\
455 456 457 458 459 460 461 462 463 464 465 466
        \n  g1.x = in_scalarsRange[c][0] + (\
        \n         in_scalarsRange[c][1] - in_scalarsRange[c][0]) * g1.x;\
        \n  g1.y = in_scalarsRange[c][0] + (\
        \n         in_scalarsRange[c][1] - in_scalarsRange[c][0]) * g1.y;\
        \n  g1.z = in_scalarsRange[c][0] + (\
        \n         in_scalarsRange[c][1] - in_scalarsRange[c][0]) * g1.z;\
        \n  g2.x = in_scalarsRange[c][0] + (\
        \n         in_scalarsRange[c][1] - in_scalarsRange[c][0]) * g2.x;\
        \n  g2.y = in_scalarsRange[c][0] + (\
        \n         in_scalarsRange[c][1] - in_scalarsRange[c][0]) * g2.y;\
        \n  g2.z = in_scalarsRange[c][0] + (\
        \n         in_scalarsRange[c][1] - in_scalarsRange[c][0]) * g2.z;\
467
        \n  g2.xyz = g1 - g2.xyz;\
468 469 470
        \n  g2.x /= g_aspect.x;\
        \n  g2.y /= g_aspect.y;\
        \n  g2.z /= g_aspect.z;\
471 472
        \n  g2.w = 0.0;\
        \n  float grad_mag = length(g2);\
473 474 475 476 477 478 479 480 481 482
        \n  if (grad_mag > 0.0)\
        \n    {\
        \n    g2.x /= grad_mag;\
        \n    g2.y /= grad_mag;\
        \n    g2.z /= grad_mag;\
        \n    }\
        \n  else\
        \n    {\
        \n    g2.xyz = vec3(0.0, 0.0, 0.0);\
        \n    }\
483 484
        \n  grad_mag = grad_mag * 1.0 / (0.25 * (in_scalarsRange[c][1] -\
        \n                                      (in_scalarsRange[c][0])));\
485 486 487
        \n  grad_mag = clamp(grad_mag, 0.0, 1.0);\
        \n  g2.w = grad_mag;\
        \n  return g2;\
488 489
        \n  }"
      );
490 491 492
      }
    else
      {
493
      shaderStr += std::string("\
494
        \nvec4 computeGradient(int component)\
495
        \n  {\
496
        \n  return vec4(0.0);\
497
        \n  }");
498
      }
499 500

    return shaderStr;
501 502 503
  }

  //--------------------------------------------------------------------------
504 505 506 507 508 509 510
  std::string ComputeLightingDeclaration(vtkRenderer* vtkNotUsed(ren),
                                         vtkVolumeMapper* vtkNotUsed(mapper),
                                         vtkVolume* vol,
                                         int noOfComponents,
                                         int independentComponents,
                                         int vtkNotUsed(numberOfLights),
                                         int lightingComplexity)
511 512
    {
    vtkVolumeProperty* volProperty = vol->GetProperty();
513
    std::string shaderStr = std::string("\
514
      \nvec4 computeLighting(vec4 color, int component)\
515 516
      \n  {\
      \n  vec4 finalColor = vec4(0.0);"
517
    );
518

519 520 521 522
    if (volProperty->GetShade() || volProperty->HasGradientOpacity())
      {
      shaderStr += std::string("\
        \n  // Compute gradient function only once\
523
        \n  vec4 gradient = computeGradient(component);"
524 525 526
      );
      }

527
    if (volProperty->GetShade())
528
      {
Aashish Chaudhary's avatar
Aashish Chaudhary committed
529 530
      if (lightingComplexity == 1)
        {
531 532 533
        shaderStr += std::string("\
          \n  vec3 diffuse = vec3(0.0);\
          \n  vec3 specular = vec3(0.0);\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
534 535
          \n  vec3 normal = gradient.xyz / in_cellSpacing;\
          \n  float normalLength = length(normal);\
536 537
          \n  if (normalLength > 0.0)\
          \n    {\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
538
          \n    normal = normalize(normal);\
539 540 541
          \n    }\
          \n  else\
          \n    {\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
542
          \n    normal = vec3(0.0, 0.0, 0.0);\
543
          \n    }\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
544 545
          \n   float nDotL = dot(normal, g_ldir);\
          \n   float nDotH = dot(normal, g_h);\
546 547 548 549 550 551 552 553
          \n   if (nDotL < 0.0 && in_twoSidedLighting)\
          \n     {\
          \n     nDotL = -nDotL;\
          \n     }\
          \n   if (nDotH < 0.0 && in_twoSidedLighting)\
          \n     {\
          \n     nDotH = -nDotH;\
          \n     }\
554
          \n   if (nDotL > 0.0)\
555 556 557 558 559 560 561 562
          \n     {\
          \n     diffuse = nDotL * in_diffuse * in_lightDiffuseColor[0]\
          \n                 * color.rgb;\
          \n     }\
          \n    specular = pow(nDotH, in_shininess) * in_specular *\
          \n                 in_lightSpecularColor[0];\
          \n  // For the headlight, ignore the light's ambient color\
          \n  // for now as it is causing the old mapper tests to fail\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
563
          \n  finalColor.xyz = in_ambient * color.rgb + diffuse + specular;"
564
          );
Aashish Chaudhary's avatar
Aashish Chaudhary committed
565 566
        }
      else if (lightingComplexity == 2)
567
        {
568
        shaderStr += std::string("\
569
          \n  g_fragWorldPos = in_modelViewMatrix * in_volumeMatrix *\
570
          \n                      in_textureDatasetMatrix * vec4(-g_dataPos, 1.0);\
571
          \n  if (g_fragWorldPos.w != 0.0)\
572
          \n   {\
573
          \n   g_fragWorldPos /= g_fragWorldPos.w;\
574
          \n   }\
575
          \n  vec3 vdir = normalize(g_fragWorldPos.xyz);\
576
          \n  vec3 normal = gradient.xyz;\
577 578 579 580 581 582
          \n  vec3 ambient = vec3(0.0);\
          \n  vec3 diffuse = vec3(0.0);\
          \n  vec3 specular = vec3(0.0);\
          \n  float normalLength = length(normal);\
          \n  if (normalLength > 0.0)\
          \n    {\
583
          \n    normal = normalize((in_texureToEyeIt * vec4(normal, 0.0)).xyz);\
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
          \n    }\
          \n  else\
          \n    {\
          \n    normal = vec3(0.0, 0.0, 0.0);\
          \n    }\
          \n  for (int lightNum = 0; lightNum < in_numberOfLights; lightNum++)\
          \n    {\
          \n    vec3 ldir = in_lightDirection[lightNum].xyz;\
          \n    vec3 h = normalize(ldir + vdir);\
          \n    float nDotH = dot(normal, h);\
          \n    if (nDotH < 0.0 && in_twoSidedLighting)\
          \n     {\
          \n     nDotH = -nDotH;\
          \n     }\
          \n  float nDotL = dot(normal, ldir);\
          \n  if (nDotL < 0.0 && in_twoSidedLighting)\
          \n    {\
          \n    nDotL = -nDotL;\
          \n    }\
603
          \n  if (nDotL > 0.0)\
604 605 606
          \n    {\
          \n    diffuse += in_lightDiffuseColor[lightNum] * nDotL;\
          \n    }\
607
          \n  if (nDotH > 0.0)\
608 609 610 611 612
          \n    {\
          \n    specular = in_lightSpecularColor[lightNum] * pow(nDotH, in_shininess);\
          \n    }\
          \n  ambient += in_lightAmbientColor[lightNum];\
          \n  }\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
613 614 615
          \n  finalColor.xyz = in_ambient * ambient +\
          \n                   in_diffuse * diffuse * color.rgb +\
          \n                   in_specular * specular;"
616
          );
617
        }
618
      else if (lightingComplexity == 3)
619
        {
620
        shaderStr += std::string("\
621
          \n  g_fragWorldPos = in_modelViewMatrix * in_volumeMatrix *\
622
          \n                      in_textureDatasetMatrix * vec4(g_dataPos, 1.0);\
623
          \n  if (g_fragWorldPos.w != 0.0)\
624
          \n    {\
625
          \n    g_fragWorldPos /= g_fragWorldPos.w;\
626
          \n    }\
627
          \n  vec3 viewDirection = normalize(-g_fragWorldPos.xyz);\
628 629 630 631
          \n  vec3 ambient = vec3(0,0,0);\
          \n  vec3 diffuse = vec3(0,0,0);\
          \n  vec3 specular = vec3(0,0,0);\
          \n  vec3 vertLightDirection;\
632
          \n  vec3 normal = normalize((in_texureToEyeIt * vec4(gradient.xyz, 0.0)).xyz);\
633 634 635 636 637 638 639 640 641 642 643 644
          \n  vec3 lightDir;\
          \n  for (int lightNum = 0; lightNum < in_numberOfLights; lightNum++)\
          \n    {\
          \n    float attenuation = 1.0;\
          \n    // directional\
          \n    lightDir = in_lightDirection[lightNum];\
          \n    if (in_lightPositional[lightNum] == 0)\
          \n      {\
          \n      vertLightDirection = lightDir;\
          \n      }\
          \n    else\
          \n      {\
645
          \n      vertLightDirection = (g_fragWorldPos.xyz - in_lightPosition[lightNum]);\
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672
          \n      float distance = length(vertLightDirection);\
          \n      vertLightDirection = normalize(vertLightDirection);\
          \n      attenuation = 1.0 /\
          \n                    (in_lightAttenuation[lightNum].x\
          \n                    + in_lightAttenuation[lightNum].y * distance\
          \n                    + in_lightAttenuation[lightNum].z * distance * distance);\
          \n      // per OpenGL standard cone angle is 90 or less for a spot light\
          \n      if (in_lightConeAngle[lightNum] <= 90.0)\
          \n        {\
          \n        float coneDot = dot(vertLightDirection, lightDir);\
          \n        // if inside the cone\
          \n        if (coneDot >= cos(radians(in_lightConeAngle[lightNum])))\
          \n          {\
          \n          attenuation = attenuation * pow(coneDot, in_lightExponent[lightNum]);\
          \n          }\
          \n        else\
          \n          {\
          \n          attenuation = 0.0;\
          \n          }\
          \n        }\
          \n      }\
          \n  // diffuse and specular lighting\
          \n  float nDotL = dot(normal, vertLightDirection);\
          \n  if (nDotL < 0.0 && in_twoSidedLighting)\
          \n    {\
          \n    nDotL = -nDotL;\
          \n    }\
673
          \n  if (nDotL > 0.0)\
674 675 676 677 678 679 680 681 682 683
          \n    {\
          \n    float df = max(0.0, attenuation * nDotL);\
          \n    diffuse += (df * in_lightDiffuseColor[lightNum]);\
          \n    }\
          \n  vec3 h = normalize(vertLightDirection + viewDirection);\
          \n  float nDotH = dot(normal, h);\
          \n  if (nDotH < 0.0 && in_twoSidedLighting)\
          \n    {\
          \n    nDotH = -nDotH;\
          \n    }\
684
          \n  if (nDotH > 0.0)\
685 686 687 688 689 690
          \n    {\
          \n    float sf = attenuation * pow(nDotH, in_shininess);\
          \n    specular += (sf * in_lightSpecularColor[lightNum]);\
          \n    }\
          \n    ambient += in_lightAmbientColor[lightNum];\
          \n  }\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
691 692
          \n  finalColor.xyz = in_ambient * ambient + in_diffuse *\
          \n                   diffuse * color.rgb + in_specular * specular;\
693
        ");
694
        }
695
      }
696 697 698
    else
      {
      shaderStr += std::string(
699
        "\n  finalColor = vec4(color.rgb, 0.0);"
700 701
      );
      }
702

703
    if (noOfComponents == 1 && volProperty->HasGradientOpacity())
704 705
      {
      shaderStr += std::string("\
706
        \n  if (gradient.w >= 0.0)\
707 708
        \n    {\
        \n    color.a = color.a *\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
709
        \n              computeGradientOpacity(gradient);\
710 711 712
        \n    }"
      );
      }
713 714 715 716 717 718 719 720 721 722
    else if (noOfComponents > 1 && independentComponents &&
             volProperty->HasGradientOpacity())
      {
      shaderStr += std::string("\
      \n  if (gradient.w >= 0.0)\
      \n    {\
      \n    for (int i = 0; i < in_noOfComponents; ++i)\
      \n      {\
      \n      color.a = color.a *\
      \n      computeGradientOpacity(gradient, i) * in_componentWeight[i];\
723 724
      \n      }\
      \n    }"
725 726
      );
      }
727 728

    shaderStr += std::string("\
Aashish Chaudhary's avatar
Aashish Chaudhary committed
729 730
      \n  finalColor.a = color.a;\
      \n  return finalColor;\
731 732 733 734
      \n  }"
    );

    return shaderStr;
735 736 737
    }

  //--------------------------------------------------------------------------
738 739 740 741
  std::string ComputeRayDirectionDeclaration(vtkRenderer* ren,
                                             vtkVolumeMapper* vtkNotUsed(mapper),
                                             vtkVolume* vtkNotUsed(vol),
                                             int vtkNotUsed(noOfComponents))
742 743 744
    {
    if (!ren->GetActiveCamera()->GetParallelProjection())
      {
745 746 747 748 749
      return std::string("\
        \nvec3 computeRayDirection()\
        \n  {\
        \n  return normalize(ip_vertexPos.xyz - g_eyePosObj.xyz);\
        \n  }");
750 751 752
      }
    else
      {
753 754 755 756 757 758 759
      return std::string("\
        \nuniform vec3 in_projectionDirection;\
        \nvec3 computeRayDirection()\
        \n  {\
        \n  return normalize((in_inverseVolumeMatrix *\
        \n                   vec4(in_projectionDirection, 0.0)).xyz);\
        \n  }");
760 761 762 763
      }
    }

  //--------------------------------------------------------------------------
764 765 766 767 768 769
  std::string ComputeColorDeclaration(vtkRenderer* vtkNotUsed(ren),
                                      vtkVolumeMapper* vtkNotUsed(mapper),
                                      vtkVolume* vtkNotUsed(vol),
                                      int noOfComponents,
                                      int independentComponents,
                                      std::map<int, std::string> colorTableMap)
770
    {
771
      if (noOfComponents == 1)
772
        {
773
        return std::string("\
774
          \nuniform sampler2D in_colorTransferFunc;\
775
          \nvec4 computeColor(vec4 scalar, float opacity)\
776
          \n  {\
777
          \n  return computeLighting(vec4(texture2D(in_colorTransferFunc,\
778
          \n                         vec2(scalar.w, 0.0)).xyz, opacity), 0);\
779
          \n  }");
780
        }
781
      else if (noOfComponents > 1 && independentComponents)
782
        {
783
        std::string shaderStr;
784
        std::ostringstream toString;
785 786
        for (int i = 0; i < noOfComponents; ++i)
          {
787
          shaderStr += std::string("\n uniform sampler2D ") +
788 789 790 791
                       colorTableMap[i] + std::string(";");
          }

        shaderStr += std::string("\
792
          \nvec4 computeColor(vec4 scalar, float opacity, int component)\
793 794 795 796 797 798 799 800 801 802
          \n  {");

        for (int i = 0; i < noOfComponents; ++i)
          {
          toString << i;
          shaderStr += std::string("\
            \n  if (component == " + toString.str() + ")");

          shaderStr += std::string("\
            \n    {\
803
            \n    return computeLighting(vec4(texture2D(\
804
            \n      "+colorTableMap[i]);
805 806
          shaderStr += std::string(", vec2(\
            \n      scalar[" + toString.str() + "],0.0)).xyz,\
807
            \n      opacity),"+toString.str()+");\
808 809 810 811 812 813
            \n    }");

          // Reset
          toString.str("");
          toString.clear();
          }
814

815
          shaderStr += std::string("\n  }");
816
          return shaderStr;
817
        }
818
      else if (noOfComponents == 2 && !independentComponents)
819 820
        {
        return std::string("\
821
          \nuniform sampler2D in_colorTransferFunc;\
822
          \nvec4 computeColor(vec4 scalar, float opacity)\
823
          \n  {\
824 825
          \n  return computeLighting(vec4(texture2D(in_colorTransferFunc,\
          \n                                        vec2(scalar.x, 0.0)).xyz,\
826
          \n                              opacity), 0);\
827 828 829 830 831
          \n  }");
        }
      else
        {
        return std::string("\
832
          \nvec4 computeColor(vec4 scalar, float opacity)\
833
          \n  {\
834
          \n  return computeLighting(vec4(scalar.xyz, opacity), 0);\
835 836
          \n  }");
        }
837 838 839
    }

  //--------------------------------------------------------------------------
840 841 842 843 844 845
  std::string ComputeOpacityDeclaration(vtkRenderer* vtkNotUsed(ren),
                                        vtkVolumeMapper* vtkNotUsed(mapper),
                                        vtkVolume* vtkNotUsed(vol),
                                        int noOfComponents,
                                        int independentComponents,
                                        std::map<int, std::string> opacityTableMap)
846
    {
847
    if (noOfComponents > 1 && independentComponents)
848
      {
849
      std::string shaderStr;
850 851
      std::ostringstream toString;

852 853
      for (int i = 0; i < noOfComponents; ++i)
        {
854
        shaderStr += std::string("\n uniform sampler2D ") +
855
                     opacityTableMap[i] + std::string(";");
856

857 858
        }

859 860 861
        shaderStr += std::string("\
          \nfloat computeOpacity(vec4 scalar, int component)\
          \n  {");
862

863 864 865 866 867 868 869 870
        for (int i = 0; i < noOfComponents; ++i)
          {
          toString << i;
          shaderStr += std::string("\
            \n  if (component == " + toString.str() + ")");

          shaderStr += std::string("\
            \n    {\
871
            \n    return texture2D(in_opacityTransferFunc");
872
          shaderStr += (i == 0 ? "" : toString.str());
873
          shaderStr += std::string(",vec2(scalar[" + toString.str() + "],0)).r;\
874 875 876 877 878 879 880 881
            \n    }");

           // Reset
           toString.str("");
           toString.clear();
           }

        shaderStr += std::string("\n  }");
882
        return shaderStr;
883
      }
884 885 886
    else if (noOfComponents == 2 && !independentComponents)
      {
      return std::string("\
887
        \nuniform sampler2D in_opacityTransferFunc;\
888 889
        \nfloat computeOpacity(vec4 scalar)\
        \n  {\
890
        \n  return texture2D(in_opacityTransferFunc, vec2(scalar.y, 0)).r;\
891 892
        \n  }");
      }
893 894 895
    else
      {
      return std::string("\
896
        \nuniform sampler2D in_opacityTransferFunc;\
897 898
        \nfloat computeOpacity(vec4 scalar)\
        \n  {\
899
        \n  return texture2D(in_opacityTransferFunc, vec2(scalar.w, 0)).r;\
900 901
        \n  }");
      }
902 903 904
    }

  //--------------------------------------------------------------------------
905 906 907
  std::string ShadingDeclarationVertex(vtkRenderer* vtkNotUsed(ren),
                                       vtkVolumeMapper* vtkNotUsed(mapper),
                                       vtkVolume* vtkNotUsed(vol))
908
    {
Aashish Chaudhary's avatar
Aashish Chaudhary committed
909
    return std::string();
910 911 912
    }

  //--------------------------------------------------------------------------
913 914 915
  std::string ShadingDeclarationFragment(vtkRenderer* vtkNotUsed(ren),
                                         vtkVolumeMapper* vtkNotUsed(mapper),
                                         vtkVolume* vtkNotUsed(vol))
916
    {
Aashish Chaudhary's avatar
Aashish Chaudhary committed
917
    return std::string();
918 919 920 921 922
    }

  //--------------------------------------------------------------------------
  std::string ShadingInit(vtkRenderer* vtkNotUsed(ren),
                          vtkVolumeMapper* mapper,
923
                          vtkVolume* vtkNotUsed(vol))
924 925 926
    {
    if (mapper->GetBlendMode() == vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND)
      {
927 928
      return std::string("\
        \n  // We get data between 0.0 - 1.0 range\
929
        \n  bool l_firstValue = true;\
930 931
        \n  vec4 l_maxValue = vec4(0.0);"
      );
932 933 934
      }
    else if (mapper->GetBlendMode() == vtkVolumeMapper::MINIMUM_INTENSITY_BLEND)
      {
935 936
      return std::string("\
        \n  //We get data between 0.0 - 1.0 range\
937
        \n  bool l_firstValue = true;\
938 939
        \n  vec4 l_minValue = vec4(1.0);"
      );
940 941 942
      }
    else if (mapper->GetBlendMode() == vtkVolumeMapper::ADDITIVE_BLEND)
      {
943 944 945 946
      return std::string("\
        \n  //We get data between 0.0 - 1.0 range\
        \n  float l_sumValue = 0.0;"
      );
947 948 949
      }
    else
      {
Aashish Chaudhary's avatar