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

  Program:   Visualization Toolkit

  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.

=========================================================================*/
#include "vtkDirect3DPolyDataMapper.h"

#include "vtkCamera.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkCommand.h"
#include "vtkFloatArray.h"
#include "vtkHardwareSelector.h"
#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkLight.h"
#include "vtkLightCollection.h"
#include "vtkMath.h"
#include "vtkMatrix3x3.h"
#include "vtkMatrix4x4.h"
#include "vtkObjectFactory.h"
#include "vtkDirect3DActor.h"
#include "vtkDirect3DBufferObject.h"
#include "vtkDirect3DCamera.h"
#include "vtkDirect3DConstantBufferObject.h"
#include "vtkDirect3DHelper.h"
#include "vtkDirect3DIndexBufferObject.h"
#include "vtkDirect3DRenderPass.h"
#include "vtkDirect3DRenderWindow.h"
#include "vtkDirect3DRenderer.h"
#include "vtkDirect3DResourceFreeCallback.h"
#include "vtkDirect3DShaderCache.h"
//#include "vtkDirect3DTexture.h"
#include "vtkDirect3DVertexBufferObject.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkProperty.h"
#include "vtkScalarsToColors.h"
#include "vtkDirect3DShaderProgram.h"
//#include "vtkTextureObject.h"
#include "vtkTransform.h"
#include "vtkUnsignedIntArray.h"

// Bring in our fragment lit shader symbols.
#include "vtkPolyDataVS.h"
#include "vtkPolyDataFS.h"
//#include "vtkPolyDataWideLineGS.h"

#include <algorithm>
#include <sstream>

#include <directxmath.h>

using namespace DirectX;

//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkDirect3DPolyDataMapper)

//-----------------------------------------------------------------------------
vtkDirect3DPolyDataMapper::vtkDirect3DPolyDataMapper()
  : UsingScalarColoring(false)
{
  this->InternalColorTexture = 0;
  this->PopulateSelectionSettings = 1;
  this->LastSelectionState = vtkHardwareSelector::MIN_KNOWN_PASS - 1;
  this->CurrentInput = 0;
  this->TempMatrix4 = vtkMatrix4x4::New();
  this->TempMatrix3 = vtkMatrix3x3::New();
  this->DrawingEdges = false;
  this->ForceTextureCoordinates = false;

  this->PrimitiveIDOffset = 0;

  this->CellScalarTexture = NULL;
  this->CellScalarBuffer = NULL;
  this->CellNormalTexture = NULL;
  this->CellNormalBuffer = NULL;

  this->HavePickScalars = false;
  this->HaveCellScalars = false;
  this->HaveCellNormals = false;

  this->PointIdArrayName = NULL;
  this->CellIdArrayName = NULL;
  this->ProcessIdArrayName = NULL;
  this->CompositeIdArrayName = NULL;
  this->VBO = vtkDirect3DVertexBufferObject::New();

  this->LastBoundBO = NULL;

  this->VertexShaderCode = 0;
  this->FragmentShaderCode = 0;
  this->GeometryShaderCode = 0;

  this->LastLightComplexity[&this->Points] = -1;
  this->LastLightComplexity[&this->Lines] = -1;
  this->LastLightComplexity[&this->Tris] = -1;
  this->LastLightComplexity[&this->TriStrips] = -1;
  this->LastLightComplexity[&this->TrisEdges] = -1;
  this->LastLightComplexity[&this->TriStripsEdges] = -1;
}

//-----------------------------------------------------------------------------
vtkDirect3DPolyDataMapper::~vtkDirect3DPolyDataMapper()
{
  // if (this->InternalColorTexture)
  // { // Resources released previously.
  //   this->InternalColorTexture->Delete();
  //   this->InternalColorTexture = 0;
  // }
  this->TempMatrix3->Delete();
  this->TempMatrix4->Delete();

  // if (this->CellScalarTexture)
  // { // Resources released previously.
  //   this->CellScalarTexture->Delete();
  //   this->CellScalarTexture = 0;
  // }
  if (this->CellScalarBuffer)
  { // Resources released previously.
    this->CellScalarBuffer->Delete();
    this->CellScalarBuffer = 0;
  }

  // if (this->CellNormalTexture)
  // { // Resources released previously.
  //   this->CellNormalTexture->Delete();
  //   this->CellNormalTexture = 0;
  // }
  if (this->CellNormalBuffer)
  { // Resources released previously.
    this->CellNormalBuffer->Delete();
    this->CellNormalBuffer = 0;
  }

  this->SetPointIdArrayName(NULL);
  this->SetCellIdArrayName(NULL);
  this->SetProcessIdArrayName(NULL);
  this->SetCompositeIdArrayName(NULL);
  this->VBO->Delete();
  this->VBO = 0;

  this->SetVertexShaderCode(0);
  this->SetFragmentShaderCode(0);
  this->SetGeometryShaderCode(0);
}

//-----------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::ReleaseGraphicsResources(vtkWindow* win)
{
  this->VBO->ReleaseGraphicsResources();
  this->Points.ReleaseGraphicsResources(win);
  this->Lines.ReleaseGraphicsResources(win);
  this->Tris.ReleaseGraphicsResources(win);
  this->TriStrips.ReleaseGraphicsResources(win);
  this->TrisEdges.ReleaseGraphicsResources(win);
  this->TriStripsEdges.ReleaseGraphicsResources(win);

  // if (this->InternalColorTexture)
  // {
  //   this->InternalColorTexture->ReleaseGraphicsResources(win);
  // }
  // if (this->CellScalarTexture)
  // {
  //   this->CellScalarTexture->ReleaseGraphicsResources(win);
  // }
  if (this->CellScalarBuffer)
  {
    this->CellScalarBuffer->ReleaseGraphicsResources();
  }
  // if (this->CellNormalTexture)
  // {
  //   this->CellNormalTexture->ReleaseGraphicsResources(win);
  // }
  if (this->CellNormalBuffer)
  {
    this->CellNormalBuffer->ReleaseGraphicsResources();
  }

  this->VBOBuildString = "";
  this->IBOBuildString = "";
  this->Modified();
}

void vtkDirect3DPolyDataMapper::AddShaderReplacement(
    vtkDirect3DShader::Type shaderType, // vertex, fragment, etc
    std::string originalValue,
    bool replaceFirst,  // do this replacement before the default
    std::string replacementValue,
    bool replaceAll)
{
  vtkDirect3DPolyDataMapper::ReplacementSpec spec;
  spec.ShaderType = shaderType;
  spec.OriginalValue = originalValue;
  spec.ReplaceFirst = replaceFirst;

  vtkDirect3DPolyDataMapper::ReplacementValue values;
  values.Replacement = replacementValue;
  values.ReplaceAll = replaceAll;

  this->UserShaderReplacements[spec] = values;
}

void vtkDirect3DPolyDataMapper::ClearShaderReplacement(
    vtkDirect3DShader::Type shaderType, // vertex, fragment, etc
    std::string originalValue,
    bool replaceFirst)
{
  vtkDirect3DPolyDataMapper::ReplacementSpec spec;
  spec.ShaderType = shaderType;
  spec.OriginalValue = originalValue;
  spec.ReplaceFirst = replaceFirst;

  typedef std::map<const vtkDirect3DPolyDataMapper::ReplacementSpec,
    vtkDirect3DPolyDataMapper::ReplacementValue>::iterator RIter;
  RIter found = this->UserShaderReplacements.find(spec);
  if (found == this->UserShaderReplacements.end())
  {
    this->UserShaderReplacements.erase(found);
  }
}

//-----------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::BuildShaders(
    std::map<vtkDirect3DShader::Type, vtkDirect3DShader *> shaders,
    vtkRenderer *ren, vtkActor *actor)
{
  this->GetShaderTemplate(shaders, ren, actor);

  typedef std::map<const vtkDirect3DPolyDataMapper::ReplacementSpec,
    vtkDirect3DPolyDataMapper::ReplacementValue>::const_iterator RIter;

  // user specified pre replacements
  for (RIter i = this->UserShaderReplacements.begin();
    i != this->UserShaderReplacements.end(); i++)
  {
    if (i->first.ReplaceFirst)
    {
      std::string ssrc = shaders[i->first.ShaderType]->GetSource();
      vtkDirect3DShaderProgram::Substitute(ssrc,
        i->first.OriginalValue,
        i->second.Replacement,
        i->second.ReplaceAll);
      shaders[i->first.ShaderType]->SetSource(ssrc);
    }
  }

  this->ReplaceShaderValues(shaders, ren, actor);

  // user specified post replacements
  for (RIter i = this->UserShaderReplacements.begin();
    i != this->UserShaderReplacements.end(); i++)
  {
    if (!i->first.ReplaceFirst)
    {
      std::string ssrc = shaders[i->first.ShaderType]->GetSource();
      vtkDirect3DShaderProgram::Substitute(ssrc,
        i->first.OriginalValue,
        i->second.Replacement,
        i->second.ReplaceAll);
      shaders[i->first.ShaderType]->SetSource(ssrc);
    }
  }
}

//-----------------------------------------------------------------------------
vtkMTimeType vtkDirect3DPolyDataMapper::GetRenderPassStageMTime(vtkActor *actor)
{
  vtkInformation *info = actor->GetPropertyKeys();
  vtkMTimeType renderPassMTime = 0;

  int curRenderPasses = 0;
  if (info && info->Has(vtkDirect3DRenderPass::RenderPasses()))
  {
    curRenderPasses = info->Length(vtkDirect3DRenderPass::RenderPasses());
  }

  int lastRenderPasses = 0;
  if (this->LastRenderPassInfo->Has(vtkDirect3DRenderPass::RenderPasses()))
  {
    lastRenderPasses =
        this->LastRenderPassInfo->Length(vtkDirect3DRenderPass::RenderPasses());
  }

  // Determine the last time a render pass changed stages:
  if (curRenderPasses != lastRenderPasses)
  {
    // Number of passes changed, definitely need to update.
    // Fake the time to force an update:
    renderPassMTime = VTK_UNSIGNED_LONG_MAX;
  }
  else
  {
    // Compare the current to the previous render passes:
    for (int i = 0; i < curRenderPasses; ++i)
    {
      vtkObjectBase *curRP = info->Get(vtkDirect3DRenderPass::RenderPasses(), i);
      vtkObjectBase *lastRP =
          this->LastRenderPassInfo->Get(vtkDirect3DRenderPass::RenderPasses(), i);

      if (curRP != lastRP)
      {
        // Render passes have changed. Force update:
        renderPassMTime = VTK_UNSIGNED_LONG_MAX;
        break;
      }
      else
      {
        // Render passes have not changed -- check MTime.
        vtkDirect3DRenderPass *rp = static_cast<vtkDirect3DRenderPass*>(curRP);
        renderPassMTime = std::max(renderPassMTime, rp->GetShaderStageMTime());
      }
    }
  }

  // Cache the current set of render passes for next time:
  if (info)
  {
    this->LastRenderPassInfo->CopyEntry(info,
                                        vtkDirect3DRenderPass::RenderPasses());
  }
  else
  {
    this->LastRenderPassInfo->Clear();
  }

  return renderPassMTime;
}

//-----------------------------------------------------------------------------
bool vtkDirect3DPolyDataMapper::HaveTextures(vtkActor *actor)
{
  return (this->GetNumberOfTextures(actor) > 0);
}

//-----------------------------------------------------------------------------
unsigned int vtkDirect3DPolyDataMapper::GetNumberOfTextures(vtkActor *actor)
{
  unsigned int res = 0;
  if (this->ColorTextureMap)
  {
    res++;
  }
  if (actor->GetTexture())
  {
    res++;
  }
  res += actor->GetProperty()->GetNumberOfTextures();
  return res;
}

//-----------------------------------------------------------------------------
std::vector<vtkTexture *> vtkDirect3DPolyDataMapper::GetTextures(vtkActor *actor)
{
  std::vector<vtkTexture *> res;

  // if (this->ColorTextureMap)
  // {
  //   res.push_back(this->InternalColorTexture);
  // }
  if (actor->GetTexture())
  {
    res.push_back(actor->GetTexture());
  }
  for (int i = 0; i < actor->GetProperty()->GetNumberOfTextures(); i++)
  {
    res.push_back(actor->GetProperty()->GetTexture(i));
  }
  return res;
}

//-----------------------------------------------------------------------------
bool vtkDirect3DPolyDataMapper::HaveTCoords(vtkPolyData *poly)
{
  return (this->ColorCoordinates ||
          poly->GetPointData()->GetTCoords() ||
          this->ForceTextureCoordinates);
}

//-----------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::GetShaderTemplate(
    std::map<vtkDirect3DShader::Type, vtkDirect3DShader *> shaders,
    vtkRenderer *, vtkActor *)
{
  if (this->VertexShaderCode && strcmp(this->VertexShaderCode,"") != 0)
  {
    shaders[vtkDirect3DShader::Vertex]->SetSource(this->VertexShaderCode);
  }
  else
  {
    shaders[vtkDirect3DShader::Vertex]->SetSource(vtkPolyDataVS);
  }

  if (this->FragmentShaderCode && strcmp(this->FragmentShaderCode,"") != 0)
  {
    shaders[vtkDirect3DShader::Fragment]->SetSource(this->FragmentShaderCode);
  }
  else
  {
    shaders[vtkDirect3DShader::Fragment]->SetSource(vtkPolyDataFS);
  }

  if (this->GeometryShaderCode && strcmp(this->GeometryShaderCode,"") != 0)
  {
    shaders[vtkDirect3DShader::Geometry]->SetSource(this->GeometryShaderCode);
  }
  else
  {
    shaders[vtkDirect3DShader::Geometry]->SetSource("");
  }
}

//------------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::ReplaceShaderRenderPass(
    std::map<vtkDirect3DShader::Type, vtkDirect3DShader *> shaders, vtkRenderer *,
    vtkActor *act)
{
  std::string VSSource = shaders[vtkDirect3DShader::Vertex]->GetSource();
  std::string GSSource = shaders[vtkDirect3DShader::Geometry]->GetSource();
  std::string FSSource = shaders[vtkDirect3DShader::Fragment]->GetSource();

  vtkInformation *info = act->GetPropertyKeys();
  if (info && info->Has(vtkDirect3DRenderPass::RenderPasses()))
  {
    int numRenderPasses = info->Length(vtkDirect3DRenderPass::RenderPasses());
    for (int i = 0; i < numRenderPasses; ++i)
    {
      vtkObjectBase *rpBase = info->Get(vtkDirect3DRenderPass::RenderPasses(), i);
      vtkDirect3DRenderPass *rp = static_cast<vtkDirect3DRenderPass*>(rpBase);
      if (!rp->ReplaceShaderValues(VSSource, GSSource, FSSource, this, act))
      {
        vtkErrorMacro("vtkDirect3DRenderPass::ReplaceShaderValues failed for "
                      << rp->GetClassName());
      }
    }
  }

  shaders[vtkDirect3DShader::Vertex]->SetSource(VSSource);
  shaders[vtkDirect3DShader::Geometry]->SetSource(GSSource);
  shaders[vtkDirect3DShader::Fragment]->SetSource(FSSource);
}

//------------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::ReplaceShaderColor(
  std::map<vtkDirect3DShader::Type, vtkDirect3DShader *> shaders,
  vtkRenderer *, vtkActor *actor)
{

  shaders[vtkDirect3DShader::Fragment]->GetConstantBuffer()
    ->AddUniform("opacityUniform", "float", sizeof(float));
  shaders[vtkDirect3DShader::Fragment]->GetConstantBuffer()
    ->AddUniform("ambientColorUniform", "float3", sizeof(float)*3);
  shaders[vtkDirect3DShader::Fragment]->GetConstantBuffer()
    ->AddUniform("diffuseColorUniform", "float3", sizeof(float)*3);

  std::string VSSource = shaders[vtkDirect3DShader::Vertex]->GetSource();
  std::string GSSource = shaders[vtkDirect3DShader::Geometry]->GetSource();
  std::string FSSource = shaders[vtkDirect3DShader::Fragment]->GetSource();

  // create the material/color property declarations, and VS implementation
  // these are always defined
  // add some if we have a backface property
  if (actor->GetBackfaceProperty() && !this->DrawingEdges)
  {
    shaders[vtkDirect3DShader::Fragment]->GetConstantBuffer()
      ->AddUniform("opacityUniformBF", "float", sizeof(float));
    shaders[vtkDirect3DShader::Fragment]->GetConstantBuffer()
      ->AddUniform("ambientColorUniformBF", "float3", sizeof(float)*3);
    shaders[vtkDirect3DShader::Fragment]->GetConstantBuffer()
      ->AddUniform("diffuseColorUniformBF", "float3", sizeof(float)*3);
  }
  // add more for specular
  if (this->LastLightComplexity[this->LastBoundBO])
  {
    shaders[vtkDirect3DShader::Fragment]->GetConstantBuffer()
      ->AddUniform("specularPowerUniform", "float", sizeof(float));
    shaders[vtkDirect3DShader::Fragment]->GetConstantBuffer()
      ->AddUniform("specularColorUniform", "float3", sizeof(float)*3);
    if (actor->GetBackfaceProperty())
    {
      shaders[vtkDirect3DShader::Fragment]->GetConstantBuffer()
        ->AddUniform("specularPowerUniformBF", "float", sizeof(float));
      shaders[vtkDirect3DShader::Fragment]->GetConstantBuffer()
        ->AddUniform("specularColorUniformBF", "float3", sizeof(float)*3);
    }
  }

#if 0
  // add scalar vertex coloring
  if (this->VBO->ColorComponents != 0 && !this->DrawingEdges)
  {
    colorDec += "varying vec4 vertexColorVSOutput;\n";
    vtkDirect3DShaderProgram::Substitute(VSSource,"//VTK::Color::Dec",
                        "attribute vec4 scalarColor;\n"
                        "varying vec4 vertexColorVSOutput;");
    vtkDirect3DShaderProgram::Substitute(VSSource,"//VTK::Color::Impl",
                        "vertexColorVSOutput =  scalarColor;");
    vtkDirect3DShaderProgram::Substitute(GSSource,
      "//VTK::Color::Dec",
      "in vec4 vertexColorVSOutput[];\n"
      "out vec4 vertexColorGSOutput;");
    vtkDirect3DShaderProgram::Substitute(GSSource,
      "//VTK::Color::Impl",
      "vertexColorGSOutput = vertexColorVSOutput[i];");
  }
  if (this->HaveCellScalars && !this->HavePickScalars && !this->DrawingEdges)
  {
    colorDec += "uniform samplerBuffer textureC;\n";
  }
#endif

  // now handle the more complex fragment shader implementation
  // the following are always defined variables.  We start
  // by assiging a default value from the uniform
  std::string colorImpl =
    "  float3 ambientColor;\n"
    "  float3 diffuseColor;\n"
    "  float opacity;\n";

  if (this->LastLightComplexity[this->LastBoundBO])
  {
    colorImpl +=
      "  float3 specularColor;\n"
      "  float specularPower;\n";
  }

#if 0
  if (actor->GetBackfaceProperty() && !this->DrawingEdges)
  {
    if (this->LastLightComplexity[this->LastBoundBO])
    {
      colorImpl +=
        "  if (int(gl_FrontFacing) == 0) {\n"
        "    ambientColor = ambientColorUniformBF;\n"
        "    diffuseColor = diffuseColorUniformBF;\n"
        "    specularColor = specularColorUniformBF;\n"
        "    specularPower = specularPowerUniformBF;\n"
        "    opacity = opacityUniformBF; }\n"
        "  else {\n"
        "    ambientColor = ambientColorUniform;\n"
        "    diffuseColor = diffuseColorUniform;\n"
        "    specularColor = specularColorUniform;\n"
        "    specularPower = specularPowerUniform;\n"
        "    opacity = opacityUniform; }\n";
    }
    else
    {
      colorImpl +=
        "  if (int(gl_FrontFacing) == 0) {\n"
        "    ambientColor = ambientColorUniformBF;\n"
        "    diffuseColor = diffuseColorUniformBF;\n"
        "    opacity = opacityUniformBF; }\n"
        "  else {\n"
        "    ambientColor = ambientColorUniform;\n"
        "    diffuseColor = diffuseColorUniform;\n"
        "    opacity = opacityUniform; }\n";
    }
  }
  else
#endif

  {
    colorImpl +=
      "  ambientColor = ambientColorUniform;\n"
      "  diffuseColor = diffuseColorUniform;\n"
      "  opacity = opacityUniform;\n";
    if (this->LastLightComplexity[this->LastBoundBO])
    {
      colorImpl +=
        "  specularColor = specularColorUniform;\n"
        "  specularPower = specularPowerUniform;\n";
    }
  }

#if 0
  // now handle scalar coloring
  if (this->VBO->ColorComponents != 0 && !this->DrawingEdges)
  {
    if (this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT ||
        (this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT &&
          actor->GetProperty()->GetAmbient() > actor->GetProperty()->GetDiffuse()))
    {
      vtkDirect3DShaderProgram::Substitute(FSSource,"//VTK::Color::Impl",
        colorImpl +
        "  ambientColor = vertexColorVSOutput.rgb;\n"
        "  opacity = opacity*vertexColorVSOutput.a;");
    }
    else if (this->ScalarMaterialMode == VTK_MATERIALMODE_DIFFUSE ||
        (this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT &&
          actor->GetProperty()->GetAmbient() <= actor->GetProperty()->GetDiffuse()))
    {
      vtkDirect3DShaderProgram::Substitute(FSSource,"//VTK::Color::Impl", colorImpl +
        "  diffuseColor = vertexColorVSOutput.rgb;\n"
        "  opacity = opacity*vertexColorVSOutput.a;");
    }
    else
    {
      vtkDirect3DShaderProgram::Substitute(FSSource,"//VTK::Color::Impl", colorImpl +
        "  diffuseColor = vertexColorVSOutput.rgb;\n"
        "  ambientColor = vertexColorVSOutput.rgb;\n"
        "  opacity = opacity*vertexColorVSOutput.a;");
    }
  }
  else
  {
    // are we doing scalar coloring by texture?
    if (this->InterpolateScalarsBeforeMapping &&
        this->ColorCoordinates &&
        !this->DrawingEdges)
    {
      if (this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT ||
          (this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT &&
            actor->GetProperty()->GetAmbient() > actor->GetProperty()->GetDiffuse()))
      {
        vtkDirect3DShaderProgram::Substitute(FSSource,
          "//VTK::Color::Impl", colorImpl +
          "  vec4 texColor = texture2D(texture_0, tcoordVCVSOutput.st);\n"
          "  ambientColor = texColor.rgb;\n"
          "  opacity = opacity*texColor.a;");
      }
      else if (this->ScalarMaterialMode == VTK_MATERIALMODE_DIFFUSE ||
          (this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT &&
           actor->GetProperty()->GetAmbient() <= actor->GetProperty()->GetDiffuse()))
      {
        vtkDirect3DShaderProgram::Substitute(FSSource,
          "//VTK::Color::Impl", colorImpl +
          "  vec4 texColor = texture2D(texture_0, tcoordVCVSOutput.st);\n"
          "  diffuseColor = texColor.rgb;\n"
          "  opacity = opacity*texColor.a;");
      }
      else
      {
        vtkDirect3DShaderProgram::Substitute(FSSource,
          "//VTK::Color::Impl", colorImpl +
          "vec4 texColor = texture2D(texture_0, tcoordVCVSOutput.st);\n"
          "  ambientColor = texColor.rgb;\n"
          "  diffuseColor = texColor.rgb;\n"
          "  opacity = opacity*texColor.a;");
      }
    }
    else
    {
      if (this->HaveCellScalars && !this->DrawingEdges)
      {
        if (this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT ||
            (this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT &&
              actor->GetProperty()->GetAmbient() > actor->GetProperty()->GetDiffuse()))
        {
          vtkDirect3DShaderProgram::Substitute(FSSource,
            "//VTK::Color::Impl", colorImpl +
            "  vec4 texColor = texelFetchBuffer(textureC, gl_PrimitiveID + PrimitiveIDOffset);\n"
            "  ambientColor = texColor.rgb;\n"
            "  opacity = opacity*texColor.a;"
            );
        }
        else if (this->ScalarMaterialMode == VTK_MATERIALMODE_DIFFUSE ||
            (this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT &&
             actor->GetProperty()->GetAmbient() <= actor->GetProperty()->GetDiffuse()))
        {
          vtkDirect3DShaderProgram::Substitute(FSSource,
            "//VTK::Color::Impl", colorImpl +
           "  vec4 texColor = texelFetchBuffer(textureC, gl_PrimitiveID + PrimitiveIDOffset);\n"
            "  diffuseColor = texColor.rgb;\n"
            "  opacity = opacity*texColor.a;"
            //  "  diffuseColor = vec3((gl_PrimitiveID%256)/255.0,((gl_PrimitiveID/256)%256)/255.0,1.0);\n"
            );
        }
        else
        {
          vtkDirect3DShaderProgram::Substitute(FSSource,
            "//VTK::Color::Impl", colorImpl +
            "vec4 texColor = texelFetchBuffer(textureC, gl_PrimitiveID + PrimitiveIDOffset);\n"
            "  ambientColor = texColor.rgb;\n"
            "  diffuseColor = texColor.rgb;\n"
            "  opacity = opacity*texColor.a;"
            );
        }
      }
      vtkDirect3DShaderProgram::Substitute(FSSource,"//VTK::Color::Impl", colorImpl);
    }
  }
#else
  vtkDirect3DShaderProgram::Substitute(FSSource,"//VTK::Color::Impl", colorImpl);
#endif

  shaders[vtkDirect3DShader::Vertex]->SetSource(VSSource);
  shaders[vtkDirect3DShader::Geometry]->SetSource(GSSource);
  shaders[vtkDirect3DShader::Fragment]->SetSource(FSSource);
}

void vtkDirect3DPolyDataMapper::ReplaceShaderLight(
  std::map<vtkDirect3DShader::Type, vtkDirect3DShader *> shaders,
  vtkRenderer *, vtkActor *)
{
  std::string FSSource = shaders[vtkDirect3DShader::Fragment]->GetSource();

  // check for shadow maps
  std::string shadowFactor = "";


  int lastLightComplexity = this->LastLightComplexity[this->LastBoundBO];

  switch (lastLightComplexity)
  {
    case 0: // no lighting or RENDER_VALUES
      vtkDirect3DShaderProgram::Substitute(FSSource, "//VTK::Light::Impl",
        "  result = float4(ambientColor + diffuseColor, opacity);\n"
        "  //VTK::Light::Impl\n",
        false
        );
      break;

    case 1:  // headlight
      vtkDirect3DShaderProgram::Substitute(FSSource, "//VTK::Light::Impl",
        "  float df = max(0.3, normalVCVSOutput.z);\n"
        "  float sf = pow(df, specularPower);\n"
        "  float3 diffuse = df * diffuseColor;\n"
        "  float3 specular = sf * specularColor;\n"
        "  result = float4(ambientColor + diffuse + specular, opacity);\n"
        "  //VTK::Light::Impl\n",
        false
      );
      break;

    case 2: // light kit
      vtkDirect3DShaderProgram::Substitute(FSSource,"//VTK::Light::Dec",
        // only allow for up to 6 active lights
        "uniform int numberOfLights;\n"
        // intensity weighted color
        "uniform vec3 lightColor[6];\n"
        "uniform vec3 lightDirectionVC[6]; // normalized\n"
        "uniform vec3 lightHalfAngleVC[6]; // normalized"
      );
      vtkDirect3DShaderProgram::Substitute(FSSource,"//VTK::Light::Impl",
        "vec3 diffuse = vec3(0,0,0);\n"
        "  vec3 specular = vec3(0,0,0);\n"
        "  for (int lightNum = 0; lightNum < numberOfLights; lightNum++)\n"
        "    {\n"
        "    float df = max(0.0, dot(normalVCVSOutput, -lightDirectionVC[lightNum]));\n"
        "    diffuse += ((df" + shadowFactor + ") * lightColor[lightNum]);\n"
        "    if (dot(normalVCVSOutput, lightDirectionVC[lightNum]) < 0.0)\n"
        "      {\n"
        "      float sf = pow( max(0.0, dot(lightHalfAngleVC[lightNum],normalVCVSOutput)), specularPower);\n"
        "      specular += ((sf" + shadowFactor + ") * lightColor[lightNum]);\n"
        "      }\n"
        "    }\n"
        "  diffuse = diffuse * diffuseColor;\n"
        "  specular = specular * specularColor;\n"
        "  gl_FragData[0] = vec4(ambientColor + diffuse + specular, opacity);"
        "  //VTK::Light::Impl",
        false
      );
      break;

    case 3: // positional
      vtkDirect3DShaderProgram::Substitute(FSSource,"//VTK::Light::Dec",
        // only allow for up to 6 active lights
        "uniform int numberOfLights;\n"
        // intensity weighted color
        "uniform vec3 lightColor[6];\n"
        "uniform vec3 lightDirectionVC[6]; // normalized\n"
        "uniform vec3 lightHalfAngleVC[6]; // normalized\n"
        "uniform vec3 lightPositionVC[6];\n"
        "uniform vec3 lightAttenuation[6];\n"
        "uniform float lightConeAngle[6];\n"
        "uniform float lightExponent[6];\n"
        "uniform int lightPositional[6];"
      );
      vtkDirect3DShaderProgram::Substitute(FSSource,"//VTK::Light::Impl",
        "  vec3 diffuse = vec3(0,0,0);\n"
        "  vec3 specular = vec3(0,0,0);\n"
        "  vec3 vertLightDirectionVC;\n"
        "  for (int lightNum = 0; lightNum < numberOfLights; lightNum++)\n"
        "    {\n"
        "    float attenuation = 1.0;\n"
        "    if (lightPositional[lightNum] == 0)\n"
        "      {\n"
        "      vertLightDirectionVC = lightDirectionVC[lightNum];\n"
        "      }\n"
        "    else\n"
        "      {\n"
        "      vertLightDirectionVC = vertexVC.xyz - lightPositionVC[lightNum];\n"
        "      float distanceVC = length(vertLightDirectionVC);\n"
        "      vertLightDirectionVC = normalize(vertLightDirectionVC);\n"
        "      attenuation = 1.0 /\n"
        "        (lightAttenuation[lightNum].x\n"
        "         + lightAttenuation[lightNum].y * distanceVC\n"
        "         + lightAttenuation[lightNum].z * distanceVC * distanceVC);\n"
        "      // per Direct3D standard cone angle is 90 or less for a spot light\n"
        "      if (lightConeAngle[lightNum] <= 90.0)\n"
        "        {\n"
        "        float coneDot = dot(vertLightDirectionVC, lightDirectionVC[lightNum]);\n"
        "        // if inside the cone\n"
        "        if (coneDot >= cos(radians(lightConeAngle[lightNum])))\n"
        "          {\n"
        "          attenuation = attenuation * pow(coneDot, lightExponent[lightNum]);\n"
        "          }\n"
        "        else\n"
        "          {\n"
        "          attenuation = 0.0;\n"
        "          }\n"
        "        }\n"
        "      }\n"
        "    float df = max(0.0, attenuation*dot(normalVCVSOutput, -vertLightDirectionVC));\n"
        "    diffuse += ((df" + shadowFactor + ") * lightColor[lightNum]);\n"
        "    if (dot(normalVCVSOutput, vertLightDirectionVC) < 0.0)\n"
        "      {\n"
        "      float sf = attenuation*pow( max(0.0, dot(lightHalfAngleVC[lightNum],normalVCVSOutput)), specularPower);\n"
        "      specular += ((sf" + shadowFactor + ") * lightColor[lightNum]);\n"
        "      }\n"
        "    }\n"
        "  diffuse = diffuse * diffuseColor;\n"
        "  specular = specular * specularColor;\n"
        "  gl_FragData[0] = vec4(ambientColor + diffuse + specular, opacity);\n"
        "  //VTK::Light::Impl",
        false
        );
      break;
  }

  shaders[vtkDirect3DShader::Fragment]->SetSource(FSSource);
}

void vtkDirect3DPolyDataMapper::ReplaceShaderTCoord(
  std::map<vtkDirect3DShader::Type, vtkDirect3DShader *> shaders,
  vtkRenderer *, vtkActor *actor)
{
  if (this->DrawingEdges)
  {
    return;
  }

  if (!this->HaveTextures(actor))
  {
    return;
  }

#if 0
  std::string VSSource = shaders[vtkDirect3DShader::Vertex]->GetSource();
  std::string GSSource = shaders[vtkDirect3DShader::Geometry]->GetSource();
  std::string FSSource = shaders[vtkDirect3DShader::Fragment]->GetSource();

  // handle texture transformation matrix
  vtkInformation *info = actor->GetPropertyKeys();
  if (info && info->Has(vtkProp::GeneralTextureTransform()))
  {
    vtkDirect3DShaderProgram::Substitute(VSSource, "//VTK::TCoord::Dec",
      "//VTK::TCoord::Dec\n"
      "uniform mat4 tcMatrix;",
      false);
    if (this->VBO->TCoordComponents == 1)
    {
      vtkDirect3DShaderProgram::Substitute(VSSource, "//VTK::TCoord::Impl",
        "vec4 tcoordTmp = tcMatrix*vec4(tcoordMC,0.0,0.0,1.0);\n"
        "tcoordVCVSOutput = tcoordTmp.x/tcoordTmp.w;");
    }
    else
    {
      vtkDirect3DShaderProgram::Substitute(VSSource, "//VTK::TCoord::Impl",
        "vec4 tcoordTmp = tcMatrix*vec4(tcoordMC,0.0,1.0);\n"
        "tcoordVCVSOutput = tcoordTmp.xy/tcoordTmp.w;");
    }
  }
  else
  {
    vtkDirect3DShaderProgram::Substitute(VSSource, "//VTK::TCoord::Impl",
      "tcoordVCVSOutput = tcoordMC;");
  }

  // If 1 or 2 components per coordinates
  std::string tCoordType;
  std::string tCoordImpFSPre;
  std::string tCoordImpFSPost;
  if (this->VBO->TCoordComponents == 1)
  {
    tCoordType = "float";
    tCoordImpFSPre = "vec2(";
    tCoordImpFSPost = ", 0.0)";
  }
  else
  {
    tCoordType = "vec2";
    tCoordImpFSPre = "";
    tCoordImpFSPost = "";
  }

  std::string tCoordDecFS;
  std::string tCoordImpFS;
  std::vector<vtkTexture *> textures = this->GetTextures(actor);
  for (size_t i = 0; i < textures.size(); ++i)
  {
    vtkTexture *texture = textures[i];

    // Define texture
    std::stringstream ss;
    ss << "uniform sampler2D texture_" << i << ";\n";
    tCoordDecFS += ss.str();

    // Read texture color
    ss.str("");
    ss << "vec4 tcolor_" << i << " = texture2D(texture_" << i << ", "
       << tCoordImpFSPre << "tcoordVCVSOutput" << tCoordImpFSPost << "); // Read texture color\n";

    // Update color based on texture number of components
    int tNumComp = vtkDirect3DTexture::SafeDownCast(texture)->GetTextureObject()->GetComponents();
    switch (tNumComp)
    {
      case 1:
        ss << "tcolor_" << i << " = vec4(tcolor_" << i << ".r,tcolor_" << i << ".r,tcolor_" << i << ".r,1.0)";
        break;
      case 2:
        ss << "tcolor_" << i << " = vec4(tcolor_" << i << ".r,tcolor_" << i << ".r,tcolor_" << i << ".r,tcolor_" << i << ".g)";
        break;
      case 3:
        ss << "tcolor_" << i << " = vec4(tcolor_" << i << ".r,tcolor_" << i << ".g,tcolor_" << i << ".b,1.0)";
    }
    ss << "; // Update color based on texture nbr of components \n";

    // Define final color based on texture blending
    if(i == 0)
    {
      ss << "vec4 tcolor = tcolor_" << i << "; // BLENDING: None (first texture) \n\n";
    }
    else
    {
      int tBlending = vtkDirect3DTexture::SafeDownCast(texture)->GetBlendingMode();
      switch (tBlending)
      {
        case vtkTexture::VTK_TEXTURE_BLENDING_MODE_REPLACE:
          ss << "tcolor.rgb = tcolor_" << i << ".rgb * tcolor_" << i << ".a + "
             << "tcolor.rgb * (1 - tcolor_" << i << " .a); // BLENDING: Replace\n"
             << "tcolor.a = tcolor_" << i << ".a + tcolor.a * (1 - tcolor_" << i << " .a); // BLENDING: Replace\n\n";
          break;
        case vtkTexture::VTK_TEXTURE_BLENDING_MODE_MODULATE:
          ss << "tcolor *= tcolor_" << i << "; // BLENDING: Modulate\n\n";
          break;
        case vtkTexture::VTK_TEXTURE_BLENDING_MODE_ADD:
          ss << "tcolor.rgb = tcolor_" << i << ".rgb * tcolor_" << i << ".a + "
             << "tcolor.rgb * tcolor.a; // BLENDING: Add\n"
             << "tcolor.a += tcolor_" << i << ".a; // BLENDING: Add\n\n";
          break;
        case vtkTexture::VTK_TEXTURE_BLENDING_MODE_ADD_SIGNED:
          ss << "tcolor.rgb = tcolor_" << i << ".rgb * tcolor_" << i << ".a + "
             << "tcolor.rgb * tcolor.a - 0.5; // BLENDING: Add signed\n"
             << "tcolor.a += tcolor_" << i << ".a - 0.5; // BLENDING: Add signed\n\n";
          break;
        case vtkTexture::VTK_TEXTURE_BLENDING_MODE_INTERPOLATE:
          vtkDebugMacro(<< "Interpolate blending mode not supported for Direct3D2 backend.");
          break;
        case vtkTexture::VTK_TEXTURE_BLENDING_MODE_SUBTRACT:
          ss << "tcolor.rgb -= tcolor_" << i << ".rgb * tcolor_" << i << ".a; // BLENDING: Subtract\n\n";
          break;
        default:
          vtkDebugMacro(<< "No blending mode given, ignoring this texture colors.");
          ss << "// NO BLENDING MODE: ignoring this texture colors\n";
      }
    }
    tCoordImpFS += ss.str();
  }

  // Substitute in shader files
  vtkDirect3DShaderProgram::Substitute(VSSource, "//VTK::TCoord::Dec",
    "attribute " + tCoordType + " tcoordMC;\n" +
    "varying " + tCoordType + " tcoordVCVSOutput;");
  vtkDirect3DShaderProgram::Substitute(GSSource, "//VTK::TCoord::Dec",
    "in " + tCoordType + " tcoordVCVSOutput[];\n" +
    "out " + tCoordType + " tcoordVCGSOutput;");
  vtkDirect3DShaderProgram::Substitute(GSSource, "//VTK::TCoord::Impl",
    "tcoordVCGSOutput = tcoordVCVSOutput[i];");
  vtkDirect3DShaderProgram::Substitute(FSSource, "//VTK::TCoord::Dec",
    "varying " + tCoordType + " tcoordVCVSOutput;\n" + tCoordDecFS);

  // do texture mapping except for scalar coloring case which is
  // handled above
  if (!this->InterpolateScalarsBeforeMapping || !this->ColorCoordinates)
  {
    vtkDirect3DShaderProgram::Substitute(FSSource, "//VTK::TCoord::Impl",
      tCoordImpFS + "gl_FragData[0] = clamp(gl_FragData[0],0.0,1.0) * tcolor;");
  }

  shaders[vtkDirect3DShader::Vertex]->SetSource(VSSource);
  shaders[vtkDirect3DShader::Geometry]->SetSource(GSSource);
  shaders[vtkDirect3DShader::Fragment]->SetSource(FSSource);
#endif
}

void vtkDirect3DPolyDataMapper::ReplaceShaderPicking(
  std::map<vtkDirect3DShader::Type, vtkDirect3DShader *> shaders,
  vtkRenderer *, vtkActor *)
{
  std::string FSSource = shaders[vtkDirect3DShader::Fragment]->GetSource();

  if (this->LastSelectionState >= vtkHardwareSelector::MIN_KNOWN_PASS)
  {
    if (this->HavePickScalars)
    {
      vtkDirect3DShaderProgram::Substitute(FSSource,
        "//VTK::Picking::Dec",
        "uniform samplerBuffer textureC;");
      vtkDirect3DShaderProgram::Substitute(FSSource, "//VTK::Picking::Impl",
        "  gl_FragData[0] = texelFetchBuffer(textureC, gl_PrimitiveID + PrimitiveIDOffset);\n"
        );
    }
    else
    {
      switch (this->LastSelectionState)
      {
        case vtkHardwareSelector::ID_LOW24:
          vtkDirect3DShaderProgram::Substitute(FSSource,
          "//VTK::Picking::Impl",
          "  int idx = gl_PrimitiveID + 1 + PrimitiveIDOffset;\n"
          "  gl_FragData[0] = vec4(float(idx%256)/255.0, float((idx/256)%256)/255.0, float((idx/65536)%256)/255.0, 1.0);\n");
        break;
        case vtkHardwareSelector::ID_MID24:
          // this may yerk on Direct3D ES 2.0 so no really huge meshes in ES 2.0 OK
          vtkDirect3DShaderProgram::Substitute(FSSource,
          "//VTK::Picking::Impl",
          "  int idx = (gl_PrimitiveID + 1 + PrimitiveIDOffset);\n idx = ((idx & 0xff000000) >> 24);\n"
          "  gl_FragData[0] = vec4(float(idx%256)/255.0, float((idx/256)%256)/255.0, float(idx/65536)/255.0, 1.0);\n");
        break;
        default:
          vtkDirect3DShaderProgram::Substitute(FSSource, "//VTK::Picking::Dec",
            "uniform vec3 mapperIndex;");
          vtkDirect3DShaderProgram::Substitute(FSSource,
            "//VTK::Picking::Impl",
            "  gl_FragData[0] = vec4(mapperIndex,1.0);\n");
      }
    }
  }
  shaders[vtkDirect3DShader::Fragment]->SetSource(FSSource);
}

void vtkDirect3DPolyDataMapper::ReplaceShaderClip(
  std::map<vtkDirect3DShader::Type, vtkDirect3DShader *> shaders,
  vtkRenderer *, vtkActor *)
{
  std::string VSSource = shaders[vtkDirect3DShader::Vertex]->GetSource();
  std::string FSSource = shaders[vtkDirect3DShader::Fragment]->GetSource();

  if (this->GetNumberOfClippingPlanes())
  {
    // add all the clipping planes
    int numClipPlanes = this->GetNumberOfClippingPlanes();
    if (numClipPlanes > 6)
    {
      vtkErrorMacro(<< "Direct3D has a limit of 6 clipping planes");
      numClipPlanes = 6;
    }

    vtkDirect3DShaderProgram::Substitute(VSSource, "//VTK::Clip::Dec",
      "uniform int numClipPlanes;\n"
      "uniform vec4 clipPlanes[6];\n"
      "varying float clipDistancesVSOutput[6];");
    vtkDirect3DShaderProgram::Substitute(VSSource, "//VTK::Clip::Impl",
      "for (int planeNum = 0; planeNum < numClipPlanes; planeNum++)\n"
      "    {\n"
      "    clipDistancesVSOutput[planeNum] = dot(clipPlanes[planeNum], vertexMC);\n"
      "    }\n");
    vtkDirect3DShaderProgram::Substitute(FSSource, "//VTK::Clip::Dec",
      "uniform int numClipPlanes;\n"
      "varying float clipDistancesVSOutput[6];");
    vtkDirect3DShaderProgram::Substitute(FSSource, "//VTK::Clip::Impl",
      "for (int planeNum = 0; planeNum < numClipPlanes; planeNum++)\n"
      "    {\n"
      "    if (clipDistancesVSOutput[planeNum] < 0.0) discard;\n"
      "    }\n");
  }
  shaders[vtkDirect3DShader::Vertex]->SetSource(VSSource);
  shaders[vtkDirect3DShader::Fragment]->SetSource(FSSource);
}

void vtkDirect3DPolyDataMapper::ReplaceShaderNormal(
  std::map<vtkDirect3DShader::Type, vtkDirect3DShader *> shaders,
  vtkRenderer *, vtkActor *actor)
{
  std::string FSSource = shaders[vtkDirect3DShader::Fragment]->GetSource();

  // Render points as spheres if so requested
  // To get the correct zbuffer values we have to
  // adjust the incoming z value based on the shape
  // of the sphere, See the document
  // PixelsToZBufferConversion in this directory for
  // the derivation of the equations used.
  if (this->DrawingSpheres(*this->LastBoundBO, actor))
  {
    vtkDirect3DShaderProgram::Substitute(FSSource,
      "//VTK::Normal::Dec",
      "uniform float ZCalcS;\n"
      "uniform float ZCalcR;\n"
      "uniform int cameraParallel;\n"
      );
    vtkDirect3DShaderProgram::Substitute(FSSource,
      "//VTK::Normal::Impl",

      " float xpos = 2.0*gl_PointCoord.x - 1.0;\n"
      " float ypos = 1.0 - 2.0*gl_PointCoord.y;\n"
      " float len2 = xpos*xpos+ ypos*ypos;\n"
      " if (len2 > 1.0) { discard; }\n"
      " vec3 normalVCVSOutput = normalize(\n"
      "   vec3(2.0*gl_PointCoord.x - 1.0, 1.0 - 2.0*gl_PointCoord.y, sqrt(1.0 - len2)));\n"

      " gl_FragDepth = gl_FragCoord.z + normalVCVSOutput.z*ZCalcS*ZCalcR;\n"
      " if (cameraParallel == 0) {\n"
      "  float ZCalcQ = (normalVCVSOutput.z*ZCalcR - 1.0);\n"
      "  gl_FragDepth = (ZCalcS - gl_FragCoord.z) / ZCalcQ + ZCalcS; }\n"
      );

     shaders[vtkDirect3DShader::Fragment]->SetSource(FSSource);
     return;
  }

  // Render lines as tubes if so requested
  // To get the correct zbuffer values we have to
  // adjust the incoming z value based on the shape
  // of the tube, See the document
  // PixelsToZBufferConversion in this directory for
  // the derivation of the equations used.

  // note these are not real tubes. They are wide
  // lines that are fudged a bit to look like tubes
  // this approach is simpler than the Direct3DStickMapper
  // but results in things that are not really tubes
  // for best results use points as spheres with
  // these tubes and make sure the point Width is
  // twice the tube width
  if (this->DrawingTubes(*this->LastBoundBO, actor))
  {
    std::string GSSource = shaders[vtkDirect3DShader::Geometry]->GetSource();

    vtkDirect3DShaderProgram::Substitute(FSSource,
      "//VTK::Normal::Dec",
      "varying vec3 tubeBasis1;\n"
      "varying vec3 tubeBasis2;\n"
      "uniform float ZCalcS;\n"
      "uniform float ZCalcR;\n"
      "uniform int cameraParallel;\n"
      );
    vtkDirect3DShaderProgram::Substitute(FSSource,
      "//VTK::Normal::Impl",

      "float len2 = tubeBasis1.x*tubeBasis1.x + tubeBasis1.y*tubeBasis1.y;\n"
      "float lenZ = clamp(sqrt(1.0 - len2),0.0,1.0);\n"
      "vec3 normalVCVSOutput = normalize(tubeBasis1 + tubeBasis2*lenZ);\n"
      " gl_FragDepth = gl_FragCoord.z + lenZ*ZCalcS*ZCalcR/clamp(tubeBasis2.z,0.5,1.0);\n"
      " if (cameraParallel == 0) {\n"
      "  float ZCalcQ = (lenZ*ZCalcR/clamp(tubeBasis2.z,0.5,1.0) - 1.0);\n"
      "  gl_FragDepth = (ZCalcS - gl_FragCoord.z) / ZCalcQ + ZCalcS; }\n"
      );

    vtkDirect3DShaderProgram::Substitute(GSSource,
      "//VTK::Normal::Dec",
      "in vec4 vertexVCVSOutput[];\n"
      "out vec3 tubeBasis1;\n"
      "out vec3 tubeBasis2;\n"
      );

    vtkDirect3DShaderProgram::Substitute(GSSource,
      "//VTK::Normal::Start",
      "vec3 lineDir = normalize(vertexVCVSOutput[1].xyz - vertexVCVSOutput[0].xyz);\n"
      "tubeBasis2 = normalize(cross(lineDir, vec3(normal, 0.0)));\n"
      "tubeBasis2 = tubeBasis2*sign(tubeBasis2.z);\n"
      );

    vtkDirect3DShaderProgram::Substitute(GSSource,
      "//VTK::Normal::Impl",
      "tubeBasis1 = 2.0*vec3(normal*((j+1)%2 - 0.5), 0.0);\n"
      );

    shaders[vtkDirect3DShader::Geometry]->SetSource(GSSource);
    shaders[vtkDirect3DShader::Fragment]->SetSource(FSSource);
    return;
  }

  if (this->LastLightComplexity[this->LastBoundBO] > 0)
  {
    std::string VSSource = shaders[vtkDirect3DShader::Vertex]->GetSource();
    std::string GSSource = shaders[vtkDirect3DShader::Geometry]->GetSource();

    // if we have point normals provided
    if (this->VBO->NormalOffset)
    {
      vtkDirect3DShaderProgram::Substitute(VSSource,
        "//VTK::Normal::Dec",
        "attribute vec3 normalMC;\n"
        "uniform mat3 normalMatrix;\n"
        "varying vec3 normalVCVSOutput;");
      vtkDirect3DShaderProgram::Substitute(VSSource,
        "//VTK::Normal::Impl",
        "normalVCVSOutput = normalMatrix * normalMC;");
      vtkDirect3DShaderProgram::Substitute(GSSource,
        "//VTK::Normal::Dec",
        "in vec3 normalVCVSOutput[];\n"
        "out vec3 normalVCGSOutput;");
      vtkDirect3DShaderProgram::Substitute(GSSource,
        "//VTK::Normal::Impl",
        "normalVCGSOutput = normalVCVSOutput[i];");
      vtkDirect3DShaderProgram::Substitute(FSSource,
        "//VTK::Normal::Dec",
        "varying vec3 normalVCVSOutput;");
      vtkDirect3DShaderProgram::Substitute(FSSource,
        "//VTK::Normal::Impl",
        "vec3 normalVCVSOutput = normalize(normalVCVSOutput);\n"
        //  if (!gl_FrontFacing) does not work in intel hd4000 mac
        //  if (int(gl_FrontFacing) == 0) does not work on mesa
        "  if (gl_FrontFacing == false) { normalVCVSOutput = -normalVCVSOutput; }\n"
        //"normalVC = normalVCVarying;"
        );

      shaders[vtkDirect3DShader::Vertex]->SetSource(VSSource);
      shaders[vtkDirect3DShader::Geometry]->SetSource(GSSource);
      shaders[vtkDirect3DShader::Fragment]->SetSource(FSSource);
      return;
    }

    // OK no point normals, how about cell normals
    if (this->HaveCellNormals)
    {
      vtkDirect3DShaderProgram::Substitute(FSSource,
        "//VTK::Normal::Dec",
        "uniform mat3 normalMatrix;\n"
        "uniform samplerBuffer textureN;\n");
      vtkDirect3DShaderProgram::Substitute(FSSource,
        "//VTK::Normal::Impl",
        "vec3 normalVCVSOutput = \n"
        "    texelFetchBuffer(textureN, gl_PrimitiveID + PrimitiveIDOffset).xyz;\n"
        "normalVCVSOutput = normalize(normalMatrix * normalVCVSOutput);\n"
        "  if (gl_FrontFacing == false) { normalVCVSOutput = -normalVCVSOutput; }\n"
        );
    }

    // OK we have no point or cell normals, so compute something
    // we have a forumla for wireframe
    if (actor->GetProperty()->GetRepresentation() == VTK_WIREFRAME)
    {
      // generate a normal for lines, it will be perpendicular to the line
      // and maximally aligned with the camera view direction
      // no clue if this is the best way to do this.
      // the code below has been optimized a bit so what follows is
      // an explanation of the basic approach. Compute the gradient of the line
      // with respect to x and y, the the larger of the two
      // cross that with the camera view direction. That gives a vector
      // orthogonal to the camera view and the line. Note that the line and the camera
      // view are probably not orthogonal. Which is why when we cross result that with
      // the line gradient again we get a reasonable normal. It will be othogonal to
      // the line (which is a plane but maximally aligned with the camera view.
      vtkDirect3DShaderProgram::Substitute(
            FSSource,"//VTK::UniformFlow::Impl",
            "  vec3 fdx = vec3(dFdx(vertexVC.x),dFdx(vertexVC.y),dFdx(vertexVC.z));\n"
            "  vec3 fdy = vec3(dFdy(vertexVC.x),dFdy(vertexVC.y),dFdy(vertexVC.z));\n"
            "  //VTK::UniformFlow::Impl\n" // For further replacements
            );
      vtkDirect3DShaderProgram::Substitute(FSSource,"//VTK::Normal::Impl",
        "vec3 normalVCVSOutput;\n"
        "  fdx = normalize(fdx);\n"
        "  fdy = normalize(fdy);\n"
        "  if (abs(fdx.x) > 0.0)\n"
        "    { normalVCVSOutput = normalize(cross(vec3(fdx.y, -fdx.x, 0.0), fdx)); }\n"
        "  else { normalVCVSOutput = normalize(cross(vec3(fdy.y, -fdy.x, 0.0), fdy));}"
        );
    }
    else // not lines, so surface
    {
      shaders[vtkDirect3DShader::Fragment]->GetConstantBuffer()
        ->AddUniform("cameraParallel", "int", sizeof(int));

      vtkDirect3DShaderProgram::Substitute(
            FSSource,"//VTK::UniformFlow::Impl",
            "float3 fdx = float3(ddx(vertexVC.x),ddx(vertexVC.y),ddx(vertexVC.z));\n"
            "  float3 fdy = float3(ddy(vertexVC.x),ddy(vertexVC.y),ddy(vertexVC.z));\n"
            "  //VTK::UniformFlow::Impl\n" // For further replacements
            );
      vtkDirect3DShaderProgram::Substitute(FSSource,"//VTK::Normal::Impl",
        "  fdx = normalize(fdx);\n"
        "  fdy = normalize(fdy);\n"
        "  float3 normalVCVSOutput = normalize(cross(fdx,fdy));\n"
        // the code below is faster, but does not work on some devices
        //"vec3 normalVCVSOutput = normalize(cross(dFdx(vertexVC.xyz), dFdy(vertexVC.xyz)));\n"
        "  if (cameraParallel == 1 && normalVCVSOutput.z < 0.0) { normalVCVSOutput = -1.0*normalVCVSOutput; }\n"
        "  if (cameraParallel == 0 && dot(normalVCVSOutput,vertexVC.xyz) > 0.0) { normalVCVSOutput = -1.0*normalVCVSOutput; }"
        );
    }
    shaders[vtkDirect3DShader::Fragment]->SetSource(FSSource);
  }
}

void vtkDirect3DPolyDataMapper::ReplaceShaderPositionVC(
  std::map<vtkDirect3DShader::Type, vtkDirect3DShader *> shaders,
  vtkRenderer *, vtkActor *)
{
  std::string VSSource = shaders[vtkDirect3DShader::Vertex]->GetSource();
  std::string GSSource = shaders[vtkDirect3DShader::Geometry]->GetSource();
  std::string FSSource = shaders[vtkDirect3DShader::Fragment]->GetSource();

  shaders[vtkDirect3DShader::Vertex]->GetConstantBuffer()
    ->AddUniform("MCDCMatrix", "matrix", sizeof(float)*16);

  // do we need the vertex in the shader in View Coordinates
  if (this->LastLightComplexity[this->LastBoundBO] > 0)
  {
    shaders[vtkDirect3DShader::Vertex]->GetConstantBuffer()
      ->AddUniform("MCVCMatrix", "matrix", sizeof(float)*16);
    // vtkDirect3DShaderProgram::Substitute(VSSource,
    //   "//VTK::PositionVC::Dec",
    //   "varying vec4 vertexVCVSOutput;");
    // vtkDirect3DShaderProgram::Substitute(FSSource,
    //   "//VTK::PositionVC::Dec",
    //   "varying vec4 vertexVCVSOutput;");
    vtkDirect3DShaderProgram::Substitute(FSSource,
      "//VTK::PositionVC::Impl",
      "float4 vertexVC = input.vertexVCVSOutput;\n");
    vtkDirect3DShaderProgram::Substitute(VSSource,
      "//VTK::PositionVC::Impl",
      " output.vertexVCVSOutput = mul( MCVCMatrix, input.vertexMC );\n"
      " output.Pos = mul( MCDCMatrix, input.vertexMC );\n");
  }
  else
  {
    vtkDirect3DShaderProgram::Substitute(VSSource,
      "//VTK::PositionVC::Impl",
      " output.Pos = mul( MCDCMatrix, input.vertexMC );\n");
  }
  shaders[vtkDirect3DShader::Vertex]->SetSource(VSSource);
  shaders[vtkDirect3DShader::Geometry]->SetSource(GSSource);
  shaders[vtkDirect3DShader::Fragment]->SetSource(FSSource);
}

void vtkDirect3DPolyDataMapper::ReplaceShaderPrimID(
  std::map<vtkDirect3DShader::Type, vtkDirect3DShader *> shaders,
  vtkRenderer *, vtkActor *)
{
  std::string VSSource = shaders[vtkDirect3DShader::Vertex]->GetSource();
  std::string GSSource = shaders[vtkDirect3DShader::Geometry]->GetSource();
  std::string FSSource = shaders[vtkDirect3DShader::Fragment]->GetSource();

  if (this->HaveCellNormals || this->HaveCellScalars || this->HavePickScalars)
  {
    vtkDirect3DShaderProgram::Substitute(GSSource,
      "//VTK::PrimID::Impl",
      "gl_PrimitiveID = gl_PrimitiveIDIn;");
  }
  shaders[vtkDirect3DShader::Vertex]->SetSource(VSSource);
  shaders[vtkDirect3DShader::Geometry]->SetSource(GSSource);
  shaders[vtkDirect3DShader::Fragment]->SetSource(FSSource);
}

void vtkDirect3DPolyDataMapper::ReplaceShaderCoincidentOffset(
  std::map<vtkDirect3DShader::Type, vtkDirect3DShader *> shaders,
  vtkRenderer *ren, vtkActor *actor)
{
  float factor = 0.0;
  float offset = 0.0;
  this->GetCoincidentParameters(ren, actor,factor,offset);

  // if we need an offset handle it here
  // The value of .000016 is suitable for depth buffers
  // of at least 16 bit depth. We do not query the depth
  // right now because we would need some mechanism to
  // cache the result taking into account FBO changes etc.
  if (factor != 0.0 || offset != 0.0)
  {
    std::string FSSource = shaders[vtkDirect3DShader::Fragment]->GetSource();

    vtkDirect3DShaderProgram::Substitute(FSSource,
      "//VTK::Coincident::Dec",
      "uniform float cfactor;\n"
      "uniform float coffset;");
    if (factor != 0.0)
    {
      vtkDirect3DShaderProgram::Substitute(FSSource,
        "//VTK::UniformFlow::Impl",
        "float cscale = length(vec2(dFdx(gl_FragCoord.z),dFdy(gl_FragCoord.z)));\n"
        "  //VTK::UniformFlow::Impl\n" // for other replacements
        );
      vtkDirect3DShaderProgram::Substitute(FSSource, "//VTK::Depth::Impl",
        "gl_FragDepth = gl_FragCoord.z + cfactor*cscale + 0.000016*coffset;\n");
    }
    else
    {
      vtkDirect3DShaderProgram::Substitute(FSSource,
        "//VTK::Depth::Impl",
        "gl_FragDepth = gl_FragCoord.z + 0.000016*coffset;\n"
        );
    }
    shaders[vtkDirect3DShader::Fragment]->SetSource(FSSource);
  }
}

void vtkDirect3DPolyDataMapper::ReplaceShaderDepth(
    std::map<vtkDirect3DShader::Type, vtkDirect3DShader *> shaders,
    vtkRenderer *, vtkActor *)
{
#if 0
  std::string FSSource = shaders[vtkDirect3DShader::Fragment]->GetSource();
  vtkDirect3DShaderProgram::Substitute(FSSource,"//VTK::Depth::Impl",
    "gl_FragDepth = gl_FragCoord.z;");
  shaders[vtkDirect3DShader::Fragment]->SetSource(FSSource);
#endif
}

void vtkDirect3DPolyDataMapper::ReplaceShaderValues(
  std::map<vtkDirect3DShader::Type, vtkDirect3DShader *> shaders,
  vtkRenderer *ren, vtkActor *actor)
{
  this->ReplaceShaderRenderPass(shaders, ren, actor);
  this->ReplaceShaderColor(shaders, ren, actor);
  this->ReplaceShaderNormal(shaders, ren, actor);
  this->ReplaceShaderLight(shaders, ren, actor);
  this->ReplaceShaderTCoord(shaders, ren, actor);
  this->ReplaceShaderPicking(shaders, ren, actor);
  this->ReplaceShaderClip(shaders, ren, actor);
  this->ReplaceShaderPrimID(shaders, ren, actor);
  this->ReplaceShaderPositionVC(shaders, ren, actor);
  this->ReplaceShaderCoincidentOffset(shaders, ren, actor);
  this->ReplaceShaderDepth(shaders, ren, actor);

  //cout << "VS: " << shaders[vtkDirect3DShader::Vertex]->GetSource() << endl;
  //cout << "GS: " << shaders[vtkDirect3DShader::Geometry]->GetSource() << endl;
  //cout << "FS: " << shaders[vtkDirect3DShader::Fragment]->GetSource() << endl;
}

bool vtkDirect3DPolyDataMapper::DrawingSpheres(vtkDirect3DHelper &cellBO, vtkActor *actor)
{
  return ((&cellBO == &this->Points ||
      actor->GetProperty()->GetRepresentation() == VTK_POINTS) &&
      actor->GetProperty()->GetRenderPointsAsSpheres() &&
      !this->DrawingEdges);
}

bool vtkDirect3DPolyDataMapper::DrawingTubes(vtkDirect3DHelper &cellBO, vtkActor *actor)
{
  return (actor->GetProperty()->GetRenderLinesAsTubes() &&
      (&cellBO == &this->Lines ||
       &cellBO == &this->TrisEdges ||
       &cellBO == &this->TriStripsEdges ||
       (actor->GetProperty()->GetRepresentation() == VTK_WIREFRAME &&
        &cellBO != &this->Points)));
}

//-----------------------------------------------------------------------------
bool vtkDirect3DPolyDataMapper::GetNeedToRebuildShaders(
  vtkDirect3DHelper &cellBO, vtkRenderer* ren, vtkActor *actor)
{
  int lightComplexity = 0;

  // wacky backwards compatibility with old VTK lighting
  // soooo there are many factors that determine if a primative is lit or not.
  // three that mix in a complex way are representation POINT, Interpolation FLAT
  // and having normals or not.
  bool needLighting = false;
  bool haveNormals = (this->CurrentInput->GetPointData()->GetNormals() != NULL);
  if (actor->GetProperty()->GetRepresentation() == VTK_POINTS)
  {
    needLighting = (actor->GetProperty()->GetInterpolation() != VTK_FLAT && haveNormals);
  }
  else  // wireframe or surface rep
  {
    bool isTrisOrStrips = (&cellBO == &this->Tris || &cellBO == &this->TriStrips);
    needLighting = (isTrisOrStrips ||
      (!isTrisOrStrips && actor->GetProperty()->GetInterpolation() != VTK_FLAT && haveNormals));
  }

  // we sphering or tubing? Yes I made sphere into a verb
  if (this->DrawingTubes(cellBO, actor) || this->DrawingSpheres(cellBO, actor))
  {
    needLighting = true;
  }

  // do we need lighting?
  if (actor->GetProperty()->GetLighting() && needLighting)
  {
    // consider the lighting complexity to determine which case applies
    // simple headlight, Light Kit, the whole feature set of VTK
    lightComplexity = 0;
    int numberOfLights = 0;
    vtkLightCollection *lc = ren->GetLights();
    vtkLight *light;

    vtkCollectionSimpleIterator sit;
    for(lc->InitTraversal(sit);
        (light = lc->GetNextLight(sit)); )
    {
      float status = light->GetSwitch();
      if (status > 0.0)
      {
        numberOfLights++;
        if (lightComplexity == 0)
        {
          lightComplexity = 1;
        }
      }

      if (lightComplexity == 1
          && (numberOfLights > 1
            || light->GetIntensity() != 1.0
            || light->GetLightType() != VTK_LIGHT_TYPE_HEADLIGHT))
      {
        lightComplexity = 2;
      }
      if (lightComplexity < 3
          && (light->GetPositional()))
      {
        lightComplexity = 3;
        break;
      }
    }
  }

  if (this->LastLightComplexity[&cellBO] != lightComplexity)
  {
    this->LightComplexityChanged[&cellBO].Modified();
    this->LastLightComplexity[&cellBO] = lightComplexity;
  }

  // Have the renderpasses changed?
  vtkMTimeType renderPassMTime = this->GetRenderPassStageMTime(actor);

  // has something changed that would require us to recreate the shader?
  // candidates are
  // property modified (representation interpolation and lighting)
  // input modified
  // light complexity changed
  if (cellBO.Program == 0 ||
      cellBO.ShaderSourceTime < this->GetMTime() ||
      cellBO.ShaderSourceTime < actor->GetMTime() ||
      cellBO.ShaderSourceTime < this->CurrentInput->GetMTime() ||
      cellBO.ShaderSourceTime < this->SelectionStateChanged ||
      cellBO.ShaderSourceTime < renderPassMTime ||
      cellBO.ShaderSourceTime < this->LightComplexityChanged[&cellBO]
      )
  {
    return true;
  }

  return false;
}

//-----------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::UpdateShaders(
  vtkDirect3DHelper &cellBO, vtkRenderer* ren, vtkActor *actor)
{
  vtkDirect3DRenderWindow *renWin = vtkDirect3DRenderWindow::SafeDownCast(ren->GetRenderWindow());

  this->LastBoundBO = &cellBO;

  // has something changed that would require us to recreate the shader?
  if (this->GetNeedToRebuildShaders(cellBO, ren, actor))
  {
    // build the shader source code
    std::map<vtkDirect3DShader::Type,vtkDirect3DShader *> shaders;
    vtkDirect3DShader *vss = vtkDirect3DShader::New();
    vss->SetType(vtkDirect3DShader::Vertex);
    shaders[vtkDirect3DShader::Vertex] = vss;
    vtkDirect3DShader *gss = vtkDirect3DShader::New();
    gss->SetType(vtkDirect3DShader::Geometry);
    shaders[vtkDirect3DShader::Geometry] = gss;
    vtkDirect3DShader *fss = vtkDirect3DShader::New();
    fss->SetType(vtkDirect3DShader::Fragment);
    shaders[vtkDirect3DShader::Fragment] = fss;

    this->BuildShaders(shaders, ren, actor);

    // compile and bind the program if needed
    vtkDirect3DShaderProgram *newShader =
      renWin->GetShaderCache()->ReadyShaderProgram(shaders);

    vss->Delete();
    fss->Delete();
    gss->Delete();

    // if the shader changed reinitialize the VAO
    if (newShader != cellBO.Program)
    {
      cellBO.Program = newShader;
    }

    cellBO.ShaderSourceTime.Modified();
  }
  else
  {
    renWin->GetShaderCache()->ReadyShaderProgram(cellBO.Program);
  }

  this->SetMapperShaderParameters(cellBO, ren, actor);
  this->SetPropertyShaderParameters(cellBO, ren, actor);
  this->SetCameraShaderParameters(cellBO, ren, actor);
  this->SetLightingShaderParameters(cellBO, ren, actor);

  cellBO.Program->BindConstantBuffers();

  // allow the program to set what it wants
  this->InvokeEvent(vtkCommand::UpdateShaderEvent,&cellBO);
}

void vtkDirect3DPolyDataMapper::SetMapperShaderParameters(vtkDirect3DHelper &cellBO,
                                                      vtkRenderer* ren, vtkActor *actor)
{
  // // Now to update the VAO too, if necessary.
  // cellBO.Program->SetUniformi("PrimitiveIDOffset",
  //   this->PrimitiveIDOffset);

  vtkDirect3DRenderWindow *renWin = vtkDirect3DRenderWindow::SafeDownCast(ren->GetRenderWindow());

  if (cellBO.IBO->IndexCount && (this->VBOBuildTime > cellBO.AttributeUpdateTime ||
      cellBO.ShaderSourceTime > cellBO.AttributeUpdateTime))
  {
    // Define the input layout
    D3D11_INPUT_ELEMENT_DESC layout[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
//        { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };
    UINT numElements = ARRAYSIZE( layout );

    // Create the input layout
    ID3DBlob* pVSBlob = cellBO.Program->GetVertexShaderBlob();
    HRESULT hr = renWin->GetD3DDevice()->CreateInputLayout(
      layout, numElements, pVSBlob->GetBufferPointer(),
      pVSBlob->GetBufferSize(), &cellBO.VertexLayout );

  //   if (cellBO.Program->IsAttributeUsed("vertexMC"))
  //   {
  //     if (!cellBO.VAO->AddAttributeArray(cellBO.Program, this->VBO,
  //                                        "vertexMC", this->VBO->VertexOffset,
  //                                        this->VBO->Stride, VTK_FLOAT, 3,
  //                                        false))
  //     {
  //       vtkErrorMacro(<< "Error setting 'vertexMC' in shader VAO.");
  //     }
  //   }
  //   if (this->VBO->NormalOffset && this->LastLightComplexity[&cellBO] > 0 &&
  //       cellBO.Program->IsAttributeUsed("normalMC"))
  //   {
  //     if (!cellBO.VAO->AddAttributeArray(cellBO.Program, this->VBO,
  //                                     "normalMC", this->VBO->NormalOffset,
  //                                     this->VBO->Stride, VTK_FLOAT, 3, false))
  //     {
  //       vtkErrorMacro(<< "Error setting 'normalMC' in shader VAO.");
  //     }
  //   }
  //   if (this->VBO->TCoordComponents && !this->DrawingEdges &&
  //       cellBO.Program->IsAttributeUsed("tcoordMC"))
  //   {
  //     if (!cellBO.VAO->AddAttributeArray(cellBO.Program, this->VBO,
  //                                     "tcoordMC", this->VBO->TCoordOffset,
  //                                     this->VBO->Stride, VTK_FLOAT, this->VBO->TCoordComponents, false))
  //     {
  //       vtkErrorMacro(<< "Error setting 'tcoordMC' in shader VAO.");
  //     }
  //   }
  //   if (this->VBO->ColorComponents != 0 && !this->DrawingEdges &&
  //       cellBO.Program->IsAttributeUsed("scalarColor"))
  //   {
  //     if (!cellBO.VAO->AddAttributeArray(cellBO.Program, this->VBO,
  //                                     "scalarColor", this->VBO->ColorOffset,
  //                                     this->VBO->Stride, VTK_UNSIGNED_CHAR,
  //                                     this->VBO->ColorComponents, true))
  //     {
  //       vtkErrorMacro(<< "Error setting 'scalarColor' in shader VAO.");
  //     }
  //   }

    cellBO.AttributeUpdateTime.Modified();
  }

  renWin->GetImmediateContext()->IASetInputLayout( cellBO.VertexLayout );

  // if (this->HaveTextures(actor))
  // {
  //   std::vector<vtkTexture *> textures = this->GetTextures(actor);
  //   for (size_t i = 0; i < textures.size(); ++i)
  //   {
  //     vtkTexture *texture = textures[i];
  //     std::stringstream ss; ss << "texture_" << i;
  //     std::string s = ss.str();
  //     if (texture && cellBO.Program->IsUniformUsed(s.c_str()))
  //     {
  //       int tunit = vtkDirect3DTexture::SafeDownCast(texture)->GetTextureUnit();
  //       cellBO.Program->SetUniformi(s.c_str(), tunit);
  //     }
  //   }

  //   // check for tcoord transform matrix
  //   vtkInformation *info = actor->GetPropertyKeys();
  //   vtkDirect3DCheckErrorMacro("failed after Render");
  //   if (info && info->Has(vtkProp::GeneralTextureTransform()) &&
  //       cellBO.Program->IsUniformUsed("tcMatrix"))
  //   {
  //     double *dmatrix = info->Get(vtkProp::GeneralTextureTransform());
  //     float fmatrix[16];
  //     for (int i = 0; i < 4; i++)
  //     {
  //       for (int j = 0; j < 4; j++)
  //       {
  //         fmatrix[j*4+i] = dmatrix[i*4+j];
  //       }
  //     }
  //     cellBO.Program->SetUniformMatrix4x4("tcMatrix", fmatrix);
  //     vtkDirect3DCheckErrorMacro("failed after Render");
  //   }
  // }

  // if ((this->HaveCellScalars || this->HavePickScalars) &&
  //     cellBO.Program->IsUniformUsed("textureC"))
  // {
  //   int tunit = this->CellScalarTexture->GetTextureUnit();
  //   cellBO.Program->SetUniformi("textureC", tunit);
  // }

  // if (this->HaveCellNormals && cellBO.Program->IsUniformUsed("textureN"))
  // {
  //   int tunit = this->CellNormalTexture->GetTextureUnit();
  //   cellBO.Program->SetUniformi("textureN", tunit);
  // }

  // // Handle render pass setup:
  // vtkInformation *info = actor->GetPropertyKeys();
  // if (info && info->Has(vtkDirect3DRenderPass::RenderPasses()))
  // {
  //   int numRenderPasses = info->Length(vtkDirect3DRenderPass::RenderPasses());
  //   for (int i = 0; i < numRenderPasses; ++i)
  //   {
  //     vtkObjectBase *rpBase = info->Get(vtkDirect3DRenderPass::RenderPasses(), i);
  //     vtkDirect3DRenderPass *rp = static_cast<vtkDirect3DRenderPass*>(rpBase);
  //     if (!rp->SetShaderParameters(cellBO.Program, this, actor))
  //     {
  //       vtkErrorMacro("RenderPass::SetShaderParameters failed for renderpass: "
  //                     << rp->GetClassName());
  //     }
  //   }
  // }

  // vtkHardwareSelector* selector = ren->GetSelector();
  // bool picking = (ren->GetRenderWindow()->GetIsPicking() || selector != NULL);
  // if (picking && cellBO.Program->IsUniformUsed("mapperIndex"))
  // {
  //   if (selector)
  //   {
  //     if (selector->GetCurrentPass() < vtkHardwareSelector::ID_LOW24)
  //     {
  //       cellBO.Program->SetUniform3f("mapperIndex", selector->GetPropColorValue());
  //     }
  //   }
  //   else
  //   {
  //     unsigned int idx = ren->GetCurrentPickId();
  //     float color[3];
  //     vtkHardwareSelector::Convert(idx, color);
  //     cellBO.Program->SetUniform3f("mapperIndex", color);
  //   }
  // }

  // if (this->GetNumberOfClippingPlanes() &&
  //     cellBO.Program->IsUniformUsed("numClipPlanes") &&
  //     cellBO.Program->IsUniformUsed("clipPlanes"))
  // {
  //   // add all the clipping planes
  //   int numClipPlanes = this->GetNumberOfClippingPlanes();
  //   if (numClipPlanes > 6)
  //   {
  //     vtkErrorMacro(<< "Direct3D has a limit of 6 clipping planes");
  //     numClipPlanes = 6;
  //   }

  //   float planeEquations[6][4];
  //   for (int i = 0; i < numClipPlanes; i++)
  //   {
  //     double planeEquation[4];
  //     this->GetClippingPlaneInDataCoords(actor->GetMatrix(), i, planeEquation);
  //     planeEquations[i][0] = planeEquation[0];
  //     planeEquations[i][1] = planeEquation[1];
  //     planeEquations[i][2] = planeEquation[2];
  //     planeEquations[i][3] = planeEquation[3];
  //   }
  //   cellBO.Program->SetUniformi("numClipPlanes", numClipPlanes);
  //   cellBO.Program->SetUniform4fv("clipPlanes", 6, planeEquations);
  // }

  // // handle wide lines
  // if (this->HaveWideLines(ren, actor) &&
  //     cellBO.Program->IsUniformUsed("lineWidthNVC"))
  // {
  //     int vp[4];
  //     glGetIntegerv(GL_VIEWPORT, vp);
  //     float lineWidth[2];
  //     lineWidth[0] = 2.0*actor->GetProperty()->GetLineWidth()/vp[2];
  //     lineWidth[1] = 2.0*actor->GetProperty()->GetLineWidth()/vp[3];
  //     cellBO.Program->SetUniform2f("lineWidthNVC",lineWidth);
  // }

  // // handle coincident
  // if (cellBO.Program->IsUniformUsed("coffset"))
  // {
  //   float factor, offset;
  //   this->GetCoincidentParameters(ren, actor,factor,offset);
  //   cellBO.Program->SetUniformf("coffset",offset);
  //   // cfactor isn't always used when coffset is.
  //   if (cellBO.Program->IsUniformUsed("cfactor"))
  //   {
  //     cellBO.Program->SetUniformf("cfactor", factor);
  //   }
  // }
}

//-----------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::SetLightingShaderParameters(
  vtkDirect3DHelper &cellBO,
  vtkRenderer* ren,
  vtkActor *actor)
{
  // for unlit and headlight there are no lighting parameters
  if (this->LastLightComplexity[&cellBO] < 2 ||
      (this->DrawingEdges && !this->DrawingTubes(cellBO, actor)))
  {
    return;
  }

  vtkDirect3DShaderProgram *program = cellBO.Program;

  // for lightkit case there are some parameters to set
  vtkCamera *cam = ren->GetActiveCamera();
  vtkTransform* viewTF = cam->GetModelViewTransformObject();

  // // bind some light settings
  // int numberOfLights = 0;
  // vtkLightCollection *lc = ren->GetLights();
  // vtkLight *light;

  // vtkCollectionSimpleIterator sit;
  // float lightColor[6][3];
  // float lightDirection[6][3];
  // float lightHalfAngle[6][3];
  // for(lc->InitTraversal(sit);
  //     (light = lc->GetNextLight(sit)); )
  // {
  //   float status = light->GetSwitch();
  //   if (status > 0.0)
  //   {
  //     double *dColor = light->GetDiffuseColor();
  //     double intensity = light->GetIntensity();
  //     if (renderLuminance)
  //     {
  //       lightColor[numberOfLights][0] = intensity;
  //       lightColor[numberOfLights][1] = intensity;
  //       lightColor[numberOfLights][2] = intensity;
  //     }
  //     else
  //     {
  //       lightColor[numberOfLights][0] = dColor[0] * intensity;
  //       lightColor[numberOfLights][1] = dColor[1] * intensity;
  //       lightColor[numberOfLights][2] = dColor[2] * intensity;
  //     }
  //     // get required info from light
  //     double *lfp = light->GetTransformedFocalPoint();
  //     double *lp = light->GetTransformedPosition();
  //     double lightDir[3];
  //     vtkMath::Subtract(lfp,lp,lightDir);
  //     vtkMath::Normalize(lightDir);
  //     double *tDir = viewTF->TransformNormal(lightDir);
  //     lightDirection[numberOfLights][0] = tDir[0];
  //     lightDirection[numberOfLights][1] = tDir[1];
  //     lightDirection[numberOfLights][2] = tDir[2];
  //     lightDir[0] = -tDir[0];
  //     lightDir[1] = -tDir[1];
  //     lightDir[2] = -tDir[2]+1.0;
  //     vtkMath::Normalize(lightDir);
  //     lightHalfAngle[numberOfLights][0] = lightDir[0];
  //     lightHalfAngle[numberOfLights][1] = lightDir[1];
  //     lightHalfAngle[numberOfLights][2] = lightDir[2];
  //     numberOfLights++;
  //   }
  // }

  // program->SetUniform3fv("lightColor", numberOfLights, lightColor);
  // program->SetUniform3fv("lightDirectionVC", numberOfLights, lightDirection);
  // program->SetUniform3fv("lightHalfAngleVC", numberOfLights, lightHalfAngle);
  // program->SetUniformi("numberOfLights", numberOfLights);

  // // we are done unless we have positional lights
  // if (this->LastLightComplexity[&cellBO] < 3)
  // {
  //   return;
  // }

  // // if positional lights pass down more parameters
  // float lightAttenuation[6][3];
  // float lightPosition[6][3];
  // float lightConeAngle[6];
  // float lightExponent[6];
  // int lightPositional[6];
  // numberOfLights = 0;
  // for(lc->InitTraversal(sit);
  //     (light = lc->GetNextLight(sit)); )
  // {
  //   float status = light->GetSwitch();
  //   if (status > 0.0)
  //   {
  //     double *attn = light->GetAttenuationValues();
  //     lightAttenuation[numberOfLights][0] = attn[0];
  //     lightAttenuation[numberOfLights][1] = attn[1];
  //     lightAttenuation[numberOfLights][2] = attn[2];
  //     lightExponent[numberOfLights] = light->GetExponent();
  //     lightConeAngle[numberOfLights] = light->GetConeAngle();
  //     double *lp = light->GetTransformedPosition();
  //     double *tlp = viewTF->TransformPoint(lp);
  //     lightPosition[numberOfLights][0] = tlp[0];
  //     lightPosition[numberOfLights][1] = tlp[1];
  //     lightPosition[numberOfLights][2] = tlp[2];
  //     lightPositional[numberOfLights] = light->GetPositional();
  //     numberOfLights++;
  //   }
  // }
  // program->SetUniform3fv("lightAttenuation", numberOfLights, lightAttenuation);
  // program->SetUniform1iv("lightPositional", numberOfLights, lightPositional);
  // program->SetUniform3fv("lightPositionVC", numberOfLights, lightPosition);
  // program->SetUniform1fv("lightExponent", numberOfLights, lightExponent);
  // program->SetUniform1fv("lightConeAngle", numberOfLights, lightConeAngle);
}

//-----------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::SetCameraShaderParameters(vtkDirect3DHelper &cellBO,
                                                    vtkRenderer* ren, vtkActor *actor)
{
  vtkDirect3DShaderProgram *program = cellBO.Program;

  vtkDirect3DCamera *cam = (vtkDirect3DCamera *)(ren->GetActiveCamera());

  // [WMVD]C == {world, model, view, display} coordinates
  // E.g., WCDC == world to display coordinate transformation
  vtkMatrix4x4* wcdc;
  vtkMatrix4x4* wcvc;
  vtkMatrix3x3* norms;
  vtkMatrix4x4* vcdc;
  cam->GetKeyMatrices(ren, wcvc, norms, vcdc, wcdc);

  program->GetVertexShader()->GetConstantBuffer()
    ->SetUniformMatrix("MCDCMatrix", wcdc);
  program->GetVertexShader()->GetConstantBuffer()
    ->SetUniformMatrix("MCVCMatrix", wcvc);

    // if (this->VBO->GetCoordShiftAndScaleEnabled())
  // {
  //   if (!actor->GetIsIdentity())
  //   {
  //     vtkMatrix4x4* mcwc;
  //     vtkMatrix3x3* anorms;
  //     ((vtkDirect3DActor*)actor)->GetKeyMatrices(mcwc,anorms);
  //     vtkMatrix4x4::Multiply4x4(this->VBOShiftScale.GetPointer(), mcwc, this->TempMatrix4);
  //     vtkMatrix4x4::Multiply4x4(this->TempMatrix4, wcdc, this->TempMatrix4);
  //     program->SetUniformMatrix("MCDCMatrix", this->TempMatrix4);
  //     if (program->IsUniformUsed("MCVCMatrix"))
  //     {
  //       vtkMatrix4x4::Multiply4x4(this->VBOShiftScale.GetPointer(), mcwc, this->TempMatrix4);
  //       vtkMatrix4x4::Multiply4x4(this->TempMatrix4, wcvc, this->TempMatrix4);
  //       program->SetUniformMatrix("MCVCMatrix", this->TempMatrix4);
  //     }
  //     if (program->IsUniformUsed("normalMatrix"))
  //     {
  //       vtkMatrix3x3::Multiply3x3(anorms, norms, this->TempMatrix3);
  //       program->SetUniformMatrix("normalMatrix", this->TempMatrix3);
  //     }
  //   }
  //   else
  //   {
  //     vtkMatrix4x4::Multiply4x4(this->VBOShiftScale.GetPointer(), wcdc, this->TempMatrix4);
  //     program->SetUniformMatrix("MCDCMatrix", this->TempMatrix4);
  //     if (program->IsUniformUsed("MCVCMatrix"))
  //     {
  //       vtkMatrix4x4::Multiply4x4(this->VBOShiftScale.GetPointer(), wcvc, this->TempMatrix4);
  //       program->SetUniformMatrix("MCVCMatrix", this->TempMatrix4);
  //     }
  //     if (program->IsUniformUsed("normalMatrix"))
  //     {
  //       program->SetUniformMatrix("normalMatrix", norms);
  //     }
  //   }
  // }
  // else
  // {
  //   if (!actor->GetIsIdentity())
  //   {
  //     vtkMatrix4x4 *mcwc;
  //     vtkMatrix3x3 *anorms;
  //     ((vtkDirect3DActor *)actor)->GetKeyMatrices(mcwc,anorms);
  //     vtkMatrix4x4::Multiply4x4(mcwc, wcdc, this->TempMatrix4);
  //     program->SetUniformMatrix("MCDCMatrix", this->TempMatrix4);
  //     if (program->IsUniformUsed("MCVCMatrix"))
  //     {
  //       vtkMatrix4x4::Multiply4x4(mcwc, wcvc, this->TempMatrix4);
  //       program->SetUniformMatrix("MCVCMatrix", this->TempMatrix4);
  //     }
  //     if (program->IsUniformUsed("normalMatrix"))
  //     {
  //       vtkMatrix3x3::Multiply3x3(anorms, norms, this->TempMatrix3);
  //       program->SetUniformMatrix("normalMatrix", this->TempMatrix3);
  //     }
  //   }
  //   else
  //   {
  //     program->SetUniformMatrix("MCDCMatrix", wcdc);
  //     if (program->IsUniformUsed("MCVCMatrix"))
  //     {
  //       program->SetUniformMatrix("MCVCMatrix", wcvc);
  //     }
  //     if (program->IsUniformUsed("normalMatrix"))
  //     {
  //       program->SetUniformMatrix("normalMatrix", norms);
  //     }
  //   }
  // }

  // if (program->IsUniformUsed("cameraParallel"))
  {
    program->GetFragmentShader()->GetConstantBuffer()
      ->SetUniform("cameraParallel", cam->GetParallelProjection());
  }
}

//-----------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::SetPropertyShaderParameters(vtkDirect3DHelper &cellBO,
                                                       vtkRenderer*, vtkActor *actor)
{
  vtkDirect3DShaderProgram *program = cellBO.Program;

  vtkProperty *ppty = actor->GetProperty();

 {
  // Query the property for some of the properties that can be applied.
  float opacity = static_cast<float>(ppty->GetOpacity());
  double *aColor = this->DrawingEdges ?
    ppty->GetEdgeColor() : ppty->GetAmbientColor();
  double aIntensity = (this->DrawingEdges && !this->DrawingTubes(cellBO, actor))
    ? 1.0 : ppty->GetAmbient();
  float ambientColor[3] = {static_cast<float>(aColor[0] * aIntensity),
    static_cast<float>(aColor[1] * aIntensity),
    static_cast<float>(aColor[2] * aIntensity)};

  double *dColor = this->DrawingEdges ?
    ppty->GetEdgeColor() : ppty->GetDiffuseColor();
  double dIntensity = (this->DrawingEdges && !this->DrawingTubes(cellBO, actor))
    ? 0.0 : ppty->GetDiffuse();
  float diffuseColor[3] = {static_cast<float>(dColor[0] * dIntensity),
    static_cast<float>(dColor[1] * dIntensity),
    static_cast<float>(dColor[2] * dIntensity)};

  double *sColor = ppty->GetSpecularColor();
  double sIntensity = (this->DrawingEdges && !this->DrawingTubes(cellBO, actor))
    ? 0.0 : ppty->GetSpecular();
  float specularColor[3] = {static_cast<float>(sColor[0] * sIntensity),
    static_cast<float>(sColor[1] * sIntensity),
    static_cast<float>(sColor[2] * sIntensity)};
  float specularPower = ppty->GetSpecularPower();

  program->GetFragmentShader()->GetConstantBuffer()
    ->SetUniform("opacityUniform", opacity);
  program->GetFragmentShader()->GetConstantBuffer()
    ->SetUniformArray("ambientColorUniform", ambientColor, 3);
  program->GetFragmentShader()->GetConstantBuffer()
    ->SetUniformArray("diffuseColorUniform", diffuseColor, 3);

  // we are done unless we have lighting
  if (this->LastLightComplexity[&cellBO] < 1)
  {
    return;
  }

  program->GetFragmentShader()->GetConstantBuffer()
    ->SetUniform("specularPowerUniform", specularPower);
  program->GetFragmentShader()->GetConstantBuffer()
    ->SetUniformArray("specularColorUniform", specularColor, 3);
  }

  // // now set the backface properties if we have them
  // if (actor->GetBackfaceProperty() && !this->DrawingEdges)
  // {
  //   ppty = actor->GetBackfaceProperty();

  //   float opacity = static_cast<float>(ppty->GetOpacity());
  //   double *aColor = ppty->GetAmbientColor();
  //   double aIntensity = ppty->GetAmbient();  // ignoring renderer ambient
  //   float ambientColor[3] = {static_cast<float>(aColor[0] * aIntensity),
  //     static_cast<float>(aColor[1] * aIntensity),
  //     static_cast<float>(aColor[2] * aIntensity)};
  //   double *dColor = ppty->GetDiffuseColor();
  //   double dIntensity = ppty->GetDiffuse();
  //   float diffuseColor[3] = {static_cast<float>(dColor[0] * dIntensity),
  //     static_cast<float>(dColor[1] * dIntensity),
  //     static_cast<float>(dColor[2] * dIntensity)};
  //   double *sColor = ppty->GetSpecularColor();
  //   double sIntensity = ppty->GetSpecular();
  //   float specularColor[3] = {static_cast<float>(sColor[0] * sIntensity),
  //     static_cast<float>(sColor[1] * sIntensity),
  //     static_cast<float>(sColor[2] * sIntensity)};
  //   double specularPower = ppty->GetSpecularPower();

  //   program->SetUniformf("opacityUniformBF", opacity);
  //   program->SetUniform3f("ambientColorUniformBF", ambientColor);
  //   program->SetUniform3f("diffuseColorUniformBF", diffuseColor);
  //   // we are done unless we have lighting
  //   if (this->LastLightComplexity[&cellBO] < 1)
  //   {
  //     return;
  //   }
  //   program->SetUniform3f("specularColorUniformBF", specularColor);
  //   program->SetUniformf("specularPowerUniformBF", specularPower);
  // }

}

namespace
{
// helper to get the state of picking
int getPickState(vtkRenderer *ren)
{
  vtkHardwareSelector* selector = ren->GetSelector();
  if (selector)
  {
    return selector->GetCurrentPass();
  }

  if (ren->GetRenderWindow()->GetIsPicking())
  {
    return vtkHardwareSelector::ACTOR_PASS;
  }

  return vtkHardwareSelector::MIN_KNOWN_PASS - 1;
}
}

void vtkDirect3DPolyDataMapper::GetCoincidentParameters(
  vtkRenderer* ren, vtkActor *actor,
  float &factor, float &offset)
{
  // 1. ResolveCoincidentTopology is On and non zero for this primitive
  // type
  factor = 0.0;
  offset = 0.0;
  if ( this->GetResolveCoincidentTopology() == VTK_RESOLVE_SHIFT_ZBUFFER )
  {
    // do something rough is better than nothing
    double zRes = this->GetResolveCoincidentTopologyZShift(); // 0 is no shift 1 is big shift
    double f = zRes*4.0;
    factor = f;
  }

  vtkProperty *prop = actor->GetProperty();
  if ((this->GetResolveCoincidentTopology() == VTK_RESOLVE_POLYGON_OFFSET) ||
      (prop->GetEdgeVisibility() && prop->GetRepresentation() == VTK_SURFACE))
  {
    double f = 0.0;
    double u = 0.0;
    if (this->LastBoundBO == &this->Points ||
        prop->GetRepresentation() == VTK_POINTS)
    {
      this->GetCoincidentTopologyPointOffsetParameter(u);
    }
    else if (this->LastBoundBO == &this->Lines ||
        prop->GetRepresentation() == VTK_WIREFRAME)
    {
      this->GetCoincidentTopologyLineOffsetParameters(f,u);
    }
    else if (this->LastBoundBO == &this->Tris ||
          this->LastBoundBO == &this->TriStrips)
    {
      this->GetCoincidentTopologyPolygonOffsetParameters(f,u);
    }
    if (this->LastBoundBO == &this->TrisEdges ||
        this->LastBoundBO == &this->TriStripsEdges)
    {
      this->GetCoincidentTopologyPolygonOffsetParameters(f,u);
      f /= 2;
      u /= 2;
    }
    factor = f;
    offset = u;
  }

  // hardware picking always offset due to saved zbuffer
  // This gets you above the saved surface depth buffer.
  vtkHardwareSelector* selector = ren->GetSelector();
  if (selector &&
      selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS)
  {
    offset -= 2.0;
    return;
  }
}

//-----------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::RenderPieceStart(vtkRenderer* ren, vtkActor *actor)
{
  this->TimeToDraw = 0.0;

  vtkHardwareSelector* selector = ren->GetSelector();
  int picking = getPickState(ren);
  if (this->LastSelectionState != picking)
  {
    this->SelectionStateChanged.Modified();
    this->LastSelectionState = picking;
  }

  // render points for point picking in a special way
  if (selector &&
      selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS)
  {
//    glDepthMask(GL_FALSE);
  }
  if (selector && this->PopulateSelectionSettings)
  {
    selector->BeginRenderProp();
    if (selector->GetCurrentPass() == vtkHardwareSelector::COMPOSITE_INDEX_PASS)
    {
      selector->RenderCompositeIndex(1);
    }
    if (selector->GetCurrentPass() == vtkHardwareSelector::ID_LOW24 ||
        selector->GetCurrentPass() == vtkHardwareSelector::ID_MID24 ||
        selector->GetCurrentPass() == vtkHardwareSelector::ID_HIGH16)
    {
      selector->RenderAttributeId(0);
    }
  }

  this->PrimitiveIDOffset = 0;

  // make sure the BOs are up to date
  this->UpdateBufferObjects(ren, actor);

  // if (this->HaveCellScalars || this->HavePickScalars)
  // {
  //   this->CellScalarTexture->Activate();
  // }
  // if (this->HaveCellNormals)
  // {
  //   this->CellNormalTexture->Activate();
  // }

  // If we are coloring by texture, then load the texture map.
  // Use Map as indicator, because texture hangs around.
  // if (this->ColorTextureMap)
  // {
  //   this->InternalColorTexture->Load(ren);
  // }

  // Bind the Direct3D, this is shared between the different primitive/cell types.
  this->VBO->Bind();
  this->LastBoundBO = NULL;
}

//-----------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::RenderPieceDraw(vtkRenderer* ren, vtkActor *actor)
{
  int representation = actor->GetProperty()->GetRepresentation();

  vtkDirect3DRenderWindow *renWin =
    vtkDirect3DRenderWindow::SafeDownCast(ren->GetRenderWindow());

  // render points for point picking in a special way
  // all cell types should be rendered as points
  vtkHardwareSelector* selector = ren->GetSelector();
  bool pointPicking = false;
  if (selector &&
      selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS)
  {
    representation = VTK_POINTS;
    pointPicking = true;
  }

  // draw points
  if (this->Points.IBO->IndexCount)
  {
    // render points for point picking in a special way
    if (pointPicking)
    {
//      glPointSize(2.0);
    }

    // Update/build/etc the shader.
    this->UpdateShaders(this->Points, ren, actor);
    this->Points.IBO->Bind();
    renWin->GetImmediateContext()->IASetPrimitiveTopology(
      D3D11_PRIMITIVE_TOPOLOGY_POINTLIST );
    renWin->GetImmediateContext()->DrawIndexed(
      static_cast<UINT>(this->Points.IBO->IndexCount), 0, 0 );
    this->Points.IBO->Release();
    this->PrimitiveIDOffset += (int)this->Points.IBO->IndexCount;
  }

  // draw lines
  if (this->Lines.IBO->IndexCount)
  {
    this->UpdateShaders(this->Lines, ren, actor);
    this->Lines.IBO->Bind();
    if (representation == VTK_POINTS)
    {
      if (pointPicking)
      {
//        glPointSize(4.0);
      }
      renWin->GetImmediateContext()->IASetPrimitiveTopology(
        D3D11_PRIMITIVE_TOPOLOGY_POINTLIST );
      renWin->GetImmediateContext()->DrawIndexed(
        static_cast<UINT>(this->Lines.IBO->IndexCount), 0, 0 );
    }
    else
    {
      renWin->GetImmediateContext()->IASetPrimitiveTopology(
        D3D11_PRIMITIVE_TOPOLOGY_LINELIST );
      renWin->GetImmediateContext()->DrawIndexed(
        static_cast<UINT>(this->Lines.IBO->IndexCount), 0, 0 );
    }
    this->Lines.IBO->Release();
    this->PrimitiveIDOffset = this->PrimitiveIDOffset +
      static_cast<int>((representation == VTK_POINTS ? this->Lines.IBO->IndexCount
        : this->Lines.IBO->IndexCount/2));
  }

  D3D11_PRIMITIVE_TOPOLOGY mode = (representation == VTK_POINTS) ? D3D11_PRIMITIVE_TOPOLOGY_POINTLIST :
    (representation == VTK_WIREFRAME) ? D3D11_PRIMITIVE_TOPOLOGY_LINELIST : D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;

  // draw polygons
  if (this->Tris.IBO->IndexCount)
  {
    // First we do the triangles, update the shader, set uniforms, etc.
    this->UpdateShaders(this->Tris, ren, actor);
    this->Tris.IBO->Bind();
    if (pointPicking)
    {
//      glPointSize(6.0);
    }
    renWin->GetImmediateContext()->IASetPrimitiveTopology(mode);
    renWin->GetImmediateContext()->DrawIndexed(
      static_cast<UINT>(this->Tris.IBO->IndexCount), 0, 0 );
    this->Tris.IBO->Release();
    this->PrimitiveIDOffset = this->PrimitiveIDOffset +
      static_cast<int>((representation == VTK_POINTS ? this->Tris.IBO->IndexCount
        : (representation == VTK_WIREFRAME ? this->Tris.IBO->IndexCount/2
          : this->Tris.IBO->IndexCount/3)));
  }

  // draw strips
  if (this->TriStrips.IBO->IndexCount)
  {
    // Use the tris shader program/VAO, but triStrips ibo.
    this->UpdateShaders(this->TriStrips, ren, actor);
    this->TriStrips.IBO->Bind();
    if (pointPicking)
    {
//        glPointSize(6.0);
    }
    renWin->GetImmediateContext()->IASetPrimitiveTopology(mode);
    renWin->GetImmediateContext()->DrawIndexed(
      static_cast<UINT>(this->TriStrips.IBO->IndexCount), 0, 0 );
    this->TriStrips.IBO->Release();
    this->PrimitiveIDOffset = this->PrimitiveIDOffset +
      static_cast<int>((representation == VTK_POINTS ? this->TriStrips.IBO->IndexCount
        : (representation == VTK_WIREFRAME ? this->TriStrips.IBO->IndexCount/2
          : this->TriStrips.IBO->IndexCount/3)));
  }

  if (selector && (
        selector->GetCurrentPass() == vtkHardwareSelector::ID_LOW24 ||
        selector->GetCurrentPass() == vtkHardwareSelector::ID_MID24 ||
        selector->GetCurrentPass() == vtkHardwareSelector::ID_HIGH16))
  {
    selector->RenderAttributeId(this->PrimitiveIDOffset);
  }
}

//-----------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::RenderPieceFinish(vtkRenderer* ren,
  vtkActor *actor)
{
  vtkHardwareSelector* selector = ren->GetSelector();
  // render points for point picking in a special way
  if (selector &&
      selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS)
  {
//    glDepthMask(GL_TRUE);
  }
  if (selector && this->PopulateSelectionSettings)
  {
    selector->EndRenderProp();
  }

  if (this->LastBoundBO)
  {
  }

  this->VBO->Release();

  vtkProperty *prop = actor->GetProperty();
  bool surface_offset =
    (this->GetResolveCoincidentTopology() || prop->GetEdgeVisibility())
    && prop->GetRepresentation() == VTK_SURFACE;

  // if (this->ColorTextureMap)
  // {
  //   this->InternalColorTexture->PostRender(ren);
  // }

  // If the timer is not accurate enough, set it to a small
  // time so that it is not zero
  if (this->TimeToDraw == 0.0)
  {
    this->TimeToDraw = 0.0001;
  }

  // if (this->HaveCellScalars || this->HavePickScalars)
  // {
  //   this->CellScalarTexture->Deactivate();
  // }
  // if (this->HaveCellNormals)
  // {
  //   this->CellNormalTexture->Deactivate();
  // }

  this->UpdateProgress(1.0);
}

//-----------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::RenderPiece(vtkRenderer* ren, vtkActor *actor)
{
  // Make sure that we have been properly initialized.
  if (ren->GetRenderWindow()->CheckAbortStatus())
  {
    return;
  }

  this->CurrentInput = this->GetInput();

  if (this->CurrentInput == NULL)
  {
    vtkErrorMacro(<< "No input!");
    return;
  }

  this->InvokeEvent(vtkCommand::StartEvent,NULL);
  if (!this->Static)
  {
    this->GetInputAlgorithm()->Update();
  }
  this->InvokeEvent(vtkCommand::EndEvent,NULL);

  // if there are no points then we are done
  if (!this->CurrentInput->GetPoints())
  {
    return;
  }

  // make sure context is set on our Helper & VBO
  vtkDirect3DRenderWindow *renWin =
    static_cast<vtkDirect3DRenderWindow*>(ren->GetRenderWindow());
  this->VBO->SetContext(renWin);
  this->Points.SetContext(renWin);
  this->Lines.SetContext(renWin);
  this->Tris.SetContext(renWin);
  this->TriStrips.SetContext(renWin);

  this->RenderPieceStart(ren, actor);
  this->RenderPieceDraw(ren, actor);
  this->RenderPieceFinish(ren, actor);
}

//-------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::ComputeBounds()
{
  if (!this->GetInput())
  {
    vtkMath::UninitializeBounds(this->Bounds);
    return;
  }
  this->GetInput()->GetBounds(this->Bounds);
}

//-------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::UpdateBufferObjects(vtkRenderer *ren, vtkActor *act)
{
  // Checks for the pass's rendering mode and updates its configuration.
  // Depending on the case, updates the mapper's color mapping or allocates
  // a buffer.
  // Rebuild buffers if needed
  if (this->GetNeedToRebuildBufferObjects(ren,act))
  {
    this->BuildBufferObjects(ren,act);
  }
}

//-------------------------------------------------------------------------
bool vtkDirect3DPolyDataMapper::GetNeedToRebuildBufferObjects(
  vtkRenderer *vtkNotUsed(ren), vtkActor *act)
{
  // first do a coarse check
  if (this->VBOBuildTime < this->GetMTime() ||
      this->VBOBuildTime < act->GetMTime() ||
      this->VBOBuildTime < this->CurrentInput->GetMTime() ||
      this->VBOBuildTime < this->SelectionStateChanged)
  {
    return true;
  }
  return false;
}

// create the cell scalar array adjusted for ogl Cells


void vtkDirect3DPolyDataMapper::AppendCellTextures(
  vtkRenderer *ren,
  vtkActor *,
  vtkCellArray *prims[4],
  int representation,
  std::vector<unsigned char> &newColors,
  std::vector<float> &newNorms,
  vtkPolyData *poly)
{
  // deal with optional pick mapping arrays
  vtkHardwareSelector* selector = ren->GetSelector();
  vtkUnsignedIntArray* mapArray = NULL;
  vtkIdTypeArray* mapArrayId = NULL;
  vtkPointData *pd = poly->GetPointData();
  vtkCellData *cd = poly->GetCellData();
  vtkPoints *points = poly->GetPoints();
  if (selector)
  {
    switch (selector->GetCurrentPass())
    {
      // point data is used for process_pass which seems odd
      case vtkHardwareSelector::PROCESS_PASS:
       if (selector->GetUseProcessIdFromData())
       {
        mapArray = this->ProcessIdArrayName ?
          vtkArrayDownCast<vtkUnsignedIntArray>(
            pd->GetArray(this->ProcessIdArrayName)) : NULL;
       }
        break;
      case vtkHardwareSelector::COMPOSITE_INDEX_PASS:
        mapArray = this->CompositeIdArrayName ?
          vtkArrayDownCast<vtkUnsignedIntArray>(
            cd->GetArray(this->CompositeIdArrayName)) : NULL;
        break;
      case vtkHardwareSelector::ID_LOW24:
      case vtkHardwareSelector::ID_MID24:
        if (selector->GetFieldAssociation() ==
          vtkDataObject::FIELD_ASSOCIATION_POINTS)
        {
          mapArrayId = this->PointIdArrayName ?
            vtkArrayDownCast<vtkIdTypeArray>(
              pd->GetArray(this->PointIdArrayName)) : NULL;
        }
        else
        {
          mapArrayId = this->CellIdArrayName ?
            vtkArrayDownCast<vtkIdTypeArray>(
              cd->GetArray(this->CellIdArrayName)) : NULL;
        }
        break;
    }
  }

  this->HavePickScalars = false;
  if (selector && this->PopulateSelectionSettings &&
      (mapArray ||
        selector->GetCurrentPass() >= vtkHardwareSelector::ID_LOW24))
  {
    this->HavePickScalars = true;
  }

  // handle composite ID point picking seperately as the data is on Cells
  if (this->HavePickScalars &&
      selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS &&
      selector->GetCurrentPass() == vtkHardwareSelector::COMPOSITE_INDEX_PASS)
  {
    std::vector<unsigned char> tmpColors;
    // composite id is stored in ***CELL DATA*** but in point
    // rendering each point of each cell is rendered. So we
    // put the provided value into the texture for each point
    // of each cell
    vtkIdType* indices(NULL);
    vtkIdType npts(0);
    // for each prim type
    vtkIdType cellNum = 0;
    for (int j = 0; j < 4; j++)
    {
      for (prims[j]->InitTraversal(); prims[j]->GetNextCell(npts, indices); )
      {
        unsigned int value = mapArray->GetValue(cellNum);
        value++; // see vtkHardwareSelector.cxx ID_OFFSET
        for (int i = 0; i < npts; i++)
        {
          newColors.push_back(value & 0xff);
          newColors.push_back((value & 0xff00) >> 8);
          newColors.push_back((value & 0xff0000) >> 16);
          newColors.push_back(0xff);
        }
      } // for cell
    }
    return;
  }


  // handle point picking, all is drawn as points
  if (this->HavePickScalars &&
      selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS)
  {
    vtkIdType* indices(NULL);
    vtkIdType npts(0);

    for (int j = 0; j < 4; j++)
    {
      for (prims[j]->InitTraversal(); prims[j]->GetNextCell(npts, indices); )
      {
        for (int i=0; i < npts; ++i)
        {
          unsigned int value = indices[i];
          if (mapArrayId)
          {
            value = mapArrayId->GetValue(indices[i]);
          }
          if (mapArray)
          {
            value = mapArray->GetValue(indices[i]);
          }
          value++;
          if (selector->GetCurrentPass() == vtkHardwareSelector::ID_MID24)
          {
            value = (value & 0xff000000) >> 24;
          }
          newColors.push_back(value & 0xff);
          newColors.push_back((value & 0xff00) >> 8);
          newColors.push_back((value & 0xff0000) >> 16);
          newColors.push_back(0xff);
        }
      } // for cell
    }
    return;
  }

  // handle call based process_id picking
  if (this->HavePickScalars &&
      selector->GetCurrentPass() == vtkHardwareSelector::PROCESS_PASS)
  {
    std::vector<unsigned char> tmpColors;
    // process id is stored in point data which if we were not already
    // dealing with cell picking would be fine, but we are, so it makes our
    // job that much harder.  So we first traverse all the cells to
    // find their first point id and then use the point id to
    // lookup a process values. Then we use the map of Direct3D cells
    // to vtk cells to map into the first array
    vtkIdType* indices(NULL);
    vtkIdType npts(0);
    // for each prim type
    for (int j = 0; j < 4; j++)
    {
      for (prims[j]->InitTraversal(); prims[j]->GetNextCell(npts, indices); )
      {
        unsigned int value = mapArray->GetValue(indices[0]);
        value++;
        tmpColors.push_back(value & 0xff);
        tmpColors.push_back((value & 0xff00) >> 8);
        tmpColors.push_back((value & 0xff0000) >> 16);
        tmpColors.push_back(0xff);
      } // for cell
    }
    // now traverse the Direct3D to vtk mapping
    std::vector<unsigned int> cellCellMap;
    vtkDirect3DIndexBufferObject::CreateCellSupportArrays(
      prims, cellCellMap, representation, points);

    for (unsigned int i = 0; i < cellCellMap.size(); i++)
    {
      unsigned int value = cellCellMap[i];
      newColors.push_back(tmpColors[value*4]);
      newColors.push_back(tmpColors[value*4+1]);
      newColors.push_back(tmpColors[value*4+2]);
      newColors.push_back(tmpColors[value*4+3]);
    }
    return;
  }

  // handle cell based picking
  if (this->HaveCellScalars || this->HaveCellNormals || this->HavePickScalars)
  {
    std::vector<unsigned int> cellCellMap;
    vtkDirect3DIndexBufferObject::CreateCellSupportArrays(
      prims, cellCellMap, representation, points);

    if (this->HaveCellScalars || this->HavePickScalars)
    {
      int numComp = 4;

      if (this->HavePickScalars)
      {
        for (unsigned int i = 0; i < cellCellMap.size(); i++)
        {
          unsigned int value = cellCellMap[i];
          if (mapArray)
          {
            value = mapArray->GetValue(value);
          }
          if (mapArrayId)
          {
            value = mapArrayId->GetValue(value);
          }
          value++; // see vtkHardwareSelector.cxx ID_OFFSET
          if (selector->GetCurrentPass() == vtkHardwareSelector::ID_MID24)
          {
            value = (value & 0xff000000) >> 24;
          }
          newColors.push_back(value & 0xff);
          newColors.push_back((value & 0xff00) >> 8);
          newColors.push_back((value & 0xff0000) >> 16);
          newColors.push_back(0xff);
        }
      }
      else
      {
        numComp = this->Colors->GetNumberOfComponents();
        unsigned char *colorPtr = this->Colors->GetPointer(0);
        assert(numComp == 4);
        // use a single color value?
        if (this->FieldDataTupleId > -1 &&
            this->ScalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA)
        {
          for (unsigned int i = 0; i < cellCellMap.size(); i++)
          {
            for (int j = 0; j < numComp; j++)
            {
              newColors.push_back(colorPtr[this->FieldDataTupleId*numComp + j]);
            }
          }
        }
        else
        {
          for (unsigned int i = 0; i < cellCellMap.size(); i++)
          {
            for (int j = 0; j < numComp; j++)
            {
              newColors.push_back(colorPtr[cellCellMap[i]*numComp + j]);
            }
          }
        }
      }
    }

    if (this->HaveCellNormals)
    {
      // create the cell scalar array adjusted for ogl Cells
      vtkDataArray *n = this->CurrentInput->GetCellData()->GetNormals();
      for (unsigned int i = 0; i < cellCellMap.size(); i++)
      {
        // RGB32F requires a later version of Direct3D than 3.2
        // with 3.2 we know we have RGBA32F hence the extra value
        double *norms = n->GetTuple(cellCellMap[i]);
        newNorms.push_back(norms[0]);
        newNorms.push_back(norms[1]);
        newNorms.push_back(norms[2]);
        newNorms.push_back(0);
      }
    }
  }
}

void vtkDirect3DPolyDataMapper::BuildCellTextures(
  vtkRenderer *ren,
  vtkActor *actor,
  vtkCellArray *prims[4],
  int representation)
{
#if 0
  // create the cell scalar array adjusted for ogl Cells
  std::vector<unsigned char> newColors;
  std::vector<float> newNorms;
  this->AppendCellTextures(ren, actor, prims, representation,
    newColors, newNorms, this->CurrentInput);

  // allocate as needed
  if (this->HaveCellScalars || this->HavePickScalars)
  {
    if (!this->CellScalarTexture)
    {
      this->CellScalarTexture = vtkTextureObject::New();
      this->CellScalarBuffer = vtkDirect3DBufferObject::New();
      this->CellScalarBuffer->SetType(vtkDirect3DBufferObject::TextureBuffer);
    }
    this->CellScalarTexture->SetContext(
      static_cast<vtkDirect3DRenderWindow*>(ren->GetVTKWindow()));
    this->CellScalarBuffer->Upload(newColors,
      vtkDirect3DBufferObject::TextureBuffer);
    this->CellScalarTexture->CreateTextureBuffer(
      static_cast<unsigned int>(newColors.size()/4),
      4,
      VTK_UNSIGNED_CHAR,
      this->CellScalarBuffer);
  }

  if (this->HaveCellNormals)
  {
    if (!this->CellNormalTexture)
    {
      this->CellNormalTexture = vtkTextureObject::New();
      this->CellNormalBuffer = vtkDirect3DBufferObject::New();
      this->CellNormalBuffer->SetType(vtkDirect3DBufferObject::TextureBuffer);
    }
    this->CellNormalTexture->SetContext(
      static_cast<vtkDirect3DRenderWindow*>(ren->GetVTKWindow()));

    // do we have float texture support ?
    int ftex =
      static_cast<vtkDirect3DRenderWindow *>(ren->GetRenderWindow())->
        GetDefaultTextureInternalFormat(VTK_FLOAT, 4, false, true);

    if (ftex)
    {
      this->CellNormalBuffer->Upload(newNorms,
        vtkDirect3DBufferObject::TextureBuffer);
      this->CellNormalTexture->CreateTextureBuffer(
        static_cast<unsigned int>(newNorms.size()/4),
        4, VTK_FLOAT,
        this->CellNormalBuffer);
    }
    else
    {
      // have to convert to unsigned char if no float support
      std::vector<unsigned char> ucNewNorms;
      ucNewNorms.resize(newNorms.size());
      for (size_t i = 0; i < newNorms.size(); i++)
      {
        ucNewNorms[i] = 127.0*(newNorms[i] + 1.0);
      }
      this->CellNormalBuffer->Upload(ucNewNorms,
        vtkDirect3DBufferObject::TextureBuffer);
      this->CellNormalTexture->CreateTextureBuffer(
        static_cast<unsigned int>(newNorms.size()/4),
        4, VTK_UNSIGNED_CHAR,
        this->CellNormalBuffer);
    }
  }
#endif
}

//-------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::BuildBufferObjects(vtkRenderer *ren, vtkActor *act)
{
  vtkPolyData *poly = this->CurrentInput;

  if (poly == NULL)
  {
    return;
  }

  // For vertex coloring, this sets this->Colors as side effect.
  // For texture map coloring, this sets ColorCoordinates
  // and ColorTextureMap as a side effect.
  // I moved this out of the conditional because it is fast.
  // Color arrays are cached. If nothing has changed,
  // then the scalars do not have to be regenerted.
  this->MapScalars(1.0);

  // // If we are coloring by texture, then load the texture map.
  // if (this->ColorTextureMap)
  // {
  //   if (this->InternalColorTexture == 0)
  //   {
  //     this->InternalColorTexture = vtkDirect3DTexture::New();
  //     this->InternalColorTexture->RepeatOff();
  //   }
  //   this->InternalColorTexture->SetInputData(this->ColorTextureMap);
  // }

  this->HaveCellScalars = false;
  vtkDataArray *c = this->Colors;
  if (this->ScalarVisibility)
  {
    // We must figure out how the scalars should be mapped to the polydata.
    if ( (this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ||
          this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ||
          this->ScalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA ||
          !poly->GetPointData()->GetScalars() )
         && this->ScalarMode != VTK_SCALAR_MODE_USE_POINT_FIELD_DATA
         && this->Colors)
    {
      this->HaveCellScalars = true;
      c = NULL;
    }
  }

  this->HaveCellNormals = false;
  // Do we have cell normals?
  vtkDataArray *n =
    (act->GetProperty()->GetInterpolation() != VTK_FLAT) ? poly->GetPointData()->GetNormals() : NULL;
  if (n == NULL && poly->GetCellData()->GetNormals())
  {
    this->HaveCellNormals = true;
  }

  int representation = act->GetProperty()->GetRepresentation();
  vtkHardwareSelector* selector = ren->GetSelector();
  bool pointPicking = false;
  if (selector &&
      selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS)
  {
    representation = VTK_POINTS;
    pointPicking = true;
  }

  vtkCellArray *prims[4];
  prims[0] =  poly->GetVerts();
  prims[1] =  poly->GetLines();
  prims[2] =  poly->GetPolys();
  prims[3] =  poly->GetStrips();

  // only rebuild what we need to
  // if the data or mapper or selection state changed
  // then rebuild the cell arrays
  std::ostringstream toString;
  toString.str("");
  toString.clear();
  toString << (prims[0]->GetNumberOfCells() ? prims[0]->GetMTime() : 0) <<
    'A' << (prims[1]->GetNumberOfCells() ? prims[1]->GetMTime() : 0) <<
    'B' << (prims[2]->GetNumberOfCells() ? prims[2]->GetMTime() : 0) <<
    'C' << (prims[3]->GetNumberOfCells() ? prims[3]->GetMTime() : 0) <<
    'D' << representation <<
    'E' << this->LastSelectionState <<
    'F' << poly->GetMTime() <<
    'G' << this->GetMTime();
  if (this->CellTextureBuildString != toString.str())
  {
    this->BuildCellTextures(ren, act, prims, representation);
    this->CellTextureBuildString = toString.str();
  }

  // Set the texture if we are going to use texture
  // for coloring with a point attribute.
  vtkDataArray *tcoords = NULL;
  if (this->HaveTCoords(poly))
  {
    if (this->InterpolateScalarsBeforeMapping && this->ColorCoordinates)
    {
      tcoords = this->ColorCoordinates;
    }
    else
    {
      tcoords = poly->GetPointData()->GetTCoords();
    }
  }

  // rebuild the VBO if the data has changed we create a string for the VBO what
  // can change the VBO? points normals tcoords colors so what can change those?
  // the input data is clearly one as it can change all four items tcoords may
  // haveTextures or not colors may change based on quite a few mapping
  // parameters in the mapper
  toString.str("");
  toString.clear();
  toString << poly->GetMTime() <<
    'A' << (c ? c->GetMTime() : 1) <<
    'B' << (n ? n->GetMTime() : 1) <<
    'C' << (tcoords ? tcoords->GetMTime() : 1);

  if (this->VBOBuildString != toString.str())
  {
    // Build the VBO
    this->VBO->CreateVBO(poly->GetPoints(),
        poly->GetPoints()->GetNumberOfPoints(),
        n, tcoords,
        c ? (unsigned char *)c->GetVoidPointer(0) : NULL,
        c ? c->GetNumberOfComponents() : 0);

    // If the VBO coordinates were shifted and scaled, prepare the inverse transform
    // for application to the model->view matrix:
    if (this->VBO->GetCoordShiftAndScaleEnabled())
    {
      double shift[3];
      double scale[3];
      this->VBO->GetCoordShift(shift);
      this->VBO->GetCoordScale(scale);
      this->VBOInverseTransform->Identity();
      this->VBOInverseTransform->Translate(shift[0], shift[1], shift[2]);
      this->VBOInverseTransform->Scale(1.0/scale[0], 1.0/scale[1], 1.0/scale[2]);
      this->VBOInverseTransform->GetTranspose(this->VBOShiftScale.GetPointer());
    }
    this->VBOBuildTime.Modified();
    this->VBOBuildString = toString.str();
  }

  // now create the IBOs
  this->BuildIBO(ren, act, poly);

  // free up polydata if allocated due to apple bug
  if (poly != this->CurrentInput)
  {
    poly->Delete();
  }

}

//-------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::BuildIBO(
  vtkRenderer *ren,
  vtkActor *act,
  vtkPolyData *poly)
{
  vtkCellArray *prims[4];
  prims[0] =  poly->GetVerts();
  prims[1] =  poly->GetLines();
  prims[2] =  poly->GetPolys();
  prims[3] =  poly->GetStrips();
  int representation = act->GetProperty()->GetRepresentation();

  vtkHardwareSelector* selector = ren->GetSelector();

  if (selector &&
      selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS)
  {
    representation = VTK_POINTS;
  }

  vtkDataArray *ef = poly->GetPointData()->GetAttribute(
                    vtkDataSetAttributes::EDGEFLAG);
  vtkProperty *prop = act->GetProperty();

  bool draw_surface_with_edges =
    (prop->GetEdgeVisibility() && prop->GetRepresentation() == VTK_SURFACE);

  // do we realy need to rebuild the IBO? Since the operation is costly we
  // construst a string of values that impact the IBO and see if that string has
  // changed

  // So...polydata can return a dummy CellArray when there are no lines
  std::ostringstream toString;
  toString.str("");
  toString.clear();
  toString << (prims[0]->GetNumberOfCells() ? prims[0]->GetMTime() : 0) <<
    'A' << (prims[1]->GetNumberOfCells() ? prims[1]->GetMTime() : 0) <<
    'B' << (prims[2]->GetNumberOfCells() ? prims[2]->GetMTime() : 0) <<
    'C' << (prims[3]->GetNumberOfCells() ? prims[3]->GetMTime() : 0) <<
    'D' << representation <<
    'E' << (ef ? ef->GetMTime() : 0) <<
    'F' << draw_surface_with_edges;

  if (this->IBOBuildString != toString.str())
  {
    this->Points.IBO->CreatePointIndexBuffer(prims[0]);

    if (representation == VTK_POINTS)
    {
      this->Lines.IBO->CreatePointIndexBuffer(prims[1]);
      this->Tris.IBO->CreatePointIndexBuffer(prims[2]);
      this->TriStrips.IBO->CreatePointIndexBuffer(prims[3]);
    }
    else // WIREFRAME OR SURFACE
    {
      this->Lines.IBO->CreateLineIndexBuffer(prims[1]);

      if (representation == VTK_WIREFRAME)
      {
        if (ef)
        {
          if (ef->GetNumberOfComponents() != 1)
          {
            vtkDebugMacro(<< "Currently only 1d edge flags are supported.");
            ef = NULL;
          }
          if (!ef->IsA("vtkUnsignedCharArray"))
          {
            vtkDebugMacro(<< "Currently only unsigned char edge flags are suported.");
            ef = NULL;
          }
        }
        if (ef)
        {
          this->Tris.IBO->CreateEdgeFlagIndexBuffer(prims[2], ef);
        }
        else
        {
          this->Tris.IBO->CreateTriangleLineIndexBuffer(prims[2]);
        }
        this->TriStrips.IBO->CreateStripIndexBuffer(prims[3], true);
      }
     else // SURFACE
     {
        this->Tris.IBO->CreateTriangleIndexBuffer(prims[2], poly->GetPoints());
        this->TriStrips.IBO->CreateStripIndexBuffer(prims[3], false);
     }
    }

    // when drawing edges also build the edge IBOs
    if (draw_surface_with_edges)
    {
      if (ef)
      {
        if (ef->GetNumberOfComponents() != 1)
        {
          vtkDebugMacro(<< "Currently only 1d edge flags are supported.");
          ef = NULL;
        }
        else if (!ef->IsA("vtkUnsignedCharArray"))
        {
          vtkDebugMacro(<< "Currently only unsigned char edge flags are suported.");
          ef = NULL;
        }
      }
      if (ef)
      {
        this->TrisEdges.IBO->CreateEdgeFlagIndexBuffer(prims[2], ef);
      }
      else
      {
        this->TrisEdges.IBO->CreateTriangleLineIndexBuffer(prims[2]);
      }
      this->TriStripsEdges.IBO->CreateStripIndexBuffer(prims[3], true);
    }

    this->IBOBuildString = toString.str();
  }
}
//-----------------------------------------------------------------------------
bool vtkDirect3DPolyDataMapper::GetIsOpaque()
{
  // Straight copy of what the vtkPainterPolyDataMapper was doing.
  if (this->ScalarVisibility &&
      (this->ColorMode == VTK_COLOR_MODE_DEFAULT ||
       this->ColorMode == VTK_COLOR_MODE_DIRECT_SCALARS))
  {
    vtkPolyData* input =
      vtkPolyData::SafeDownCast(this->GetInputDataObject(0, 0));
    if (input)
    {
      int cellFlag;
      vtkDataArray* scalars = this->GetScalars(input,
        this->ScalarMode, this->ArrayAccessMode, this->ArrayId,
        this->ArrayName, cellFlag);
      if (scalars &&
          (scalars->IsA("vtkUnsignedCharArray") ||
           this->ColorMode == VTK_COLOR_MODE_DIRECT_SCALARS) &&
        (scalars->GetNumberOfComponents() ==  4 /*(RGBA)*/ ||
         scalars->GetNumberOfComponents() == 2 /*(LuminanceAlpha)*/))
      {
        int opacityIndex = scalars->GetNumberOfComponents() - 1;
        unsigned char opacity = 0;
        switch (scalars->GetDataType())
        {
          vtkTemplateMacro(
            vtkScalarsToColors::ColorToUChar(
              static_cast<VTK_TT>(scalars->GetRange(opacityIndex)[0]),
              &opacity));
        }
        if (opacity < 255)
        {
          // If the opacity is 255, despite the fact that the user specified
          // RGBA, we know that the Alpha is 100% opaque. So treat as opaque.
          return false;
        }
      }
    }
  }
  return this->Superclass::GetIsOpaque();
}

//----------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::ShallowCopy(vtkAbstractMapper *mapper)
{
  vtkDirect3DPolyDataMapper *m = vtkDirect3DPolyDataMapper::SafeDownCast(mapper);
  if (m != NULL)
  {
    this->SetPointIdArrayName(m->GetPointIdArrayName());
    this->SetCompositeIdArrayName(m->GetCompositeIdArrayName());
    this->SetProcessIdArrayName(m->GetProcessIdArrayName());
    this->SetCellIdArrayName(m->GetCellIdArrayName());
    this->SetVertexShaderCode(m->GetVertexShaderCode());
    this->SetGeometryShaderCode(m->GetGeometryShaderCode());
    this->SetFragmentShaderCode(m->GetFragmentShaderCode());
  }

  // Now do superclass
  this->vtkPolyDataMapper::ShallowCopy(mapper);
}

void vtkDirect3DPolyDataMapper::SetVBOShiftScaleMethod(int m)
{
  this->VBO->SetCoordShiftAndScaleMethod(
    static_cast<vtkDirect3DVertexBufferObject::ShiftScaleMethod>(m));
}

//-----------------------------------------------------------------------------
void vtkDirect3DPolyDataMapper::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}
