TestCompositePolyDataMapper2CustomShader.cxx 6.02 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestCompositePolyDataMapper2NaNPartial.cxx

  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 "vtkCompositePolyDataMapper2.h"

#include "vtkActor.h"
#include "vtkCamera.h"
#include "vtkFloatArray.h"
#include "vtkLookupTable.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkNew.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkSphereSource.h"
#include "vtkTrivialProducer.h"
#include "vtkShaderProperty.h"

#include <vtkTestUtilities.h>
#include <vtkRegressionTestImage.h>

void FillShaderProperty( vtkActor * actor )
{
  // Modify the shader to color based on model normal
  // To do this we have to modify the vertex shader
  // to pass the normal in model coordinates
  // through to the fragment shader. By default the normal
  // is converted to View coordinates and then passed on.
  // We keep that, but add a varying for the original normal.
  // Then we modify the fragment shader to set the diffuse color
  // based on that normal. First lets modify the vertex
  // shader
  vtkShaderProperty * sp = actor->GetShaderProperty();
  sp->AddVertexShaderReplacement(
    "//VTK::Normal::Dec", // replace the normal block
    true, // before the standard replacements
    "//VTK::Normal::Dec\n" // we still want the default
    "  out vec3 myNormalMCVSOutput;\n", //but we add this
    false // only do it once
    );
  sp->AddVertexShaderReplacement(
    "//VTK::Normal::Impl", // replace the normal block
    true, // before the standard replacements
    "//VTK::Normal::Impl\n" // we still want the default
    "  myNormalMCVSOutput = normalMC;\n", //but we add this
    false // only do it once
    );
  sp->AddVertexShaderReplacement(
    "//VTK::Color::Impl", // dummy replacement for testing clear method
    true,
    "VTK::Color::Impl\n",
    false
    );
  sp->ClearVertexShaderReplacement(
    "//VTK::Color::Impl",
    true
    );

  // now modify the fragment shader
  sp->AddFragmentShaderReplacement(
    "//VTK::Normal::Dec", // replace the normal block
    true, // before the standard replacements
    "//VTK::Normal::Dec\n" // we still want the default
    "  in vec3 myNormalMCVSOutput;\n", //but we add this
    false // only do it once
    );
  sp->AddFragmentShaderReplacement(
    "//VTK::Normal::Impl", // replace the normal block
    true, // before the standard replacements
    "//VTK::Normal::Impl\n" // we still want the default calc
    "  diffuseColor = abs(myNormalMCVSOutput);\n", //but we add this
    false // only do it once
    );
}

int TestCompositePolyDataMapper2CustomShader(int argc, char* argv[])
{
  vtkNew<vtkRenderer> renderer;

  // Generate two copies of a vtkPolyData containing the same sphere
  vtkNew<vtkSphereSource> sphereSource;
  sphereSource->Update();
  vtkPolyData *sphere = vtkPolyData::SafeDownCast(sphereSource->GetOutputDataObject(0));

  vtkSmartPointer<vtkPolyData> sphere1 = vtkSmartPointer<vtkPolyData>::Take(sphere->NewInstance());
  sphere1->DeepCopy(sphere);

  sphereSource->SetCenter(1., 0., 0.);
  sphereSource->Update();
  sphere = vtkPolyData::SafeDownCast(sphereSource->GetOutputDataObject(0));

  vtkSmartPointer<vtkPolyData> sphere2 = vtkSmartPointer<vtkPolyData>::Take(sphere->NewInstance());
  sphere2->DeepCopy(sphere);

  // Generate scalars with indices for all points on the sphere
  vtkNew<vtkFloatArray> scalars;
  scalars->SetName("Scalars");
  scalars->SetNumberOfComponents(1);
  scalars->SetNumberOfTuples(sphere1->GetNumberOfPoints());
  for (vtkIdType i = 0; i < scalars->GetNumberOfTuples(); ++i)
  {
    scalars->SetTypedComponent(i, 0, static_cast<float>(i));
  }

  // Only add scalars to sphere 1.
  sphere1->GetPointData()->SetScalars(scalars);

  vtkNew<vtkMultiBlockDataSet> mbds;
  mbds->SetNumberOfBlocks(2);
  mbds->SetBlock(0, sphere1);
  mbds->SetBlock(1, sphere2);

  vtkNew<vtkTrivialProducer> source;
  source->SetOutput(mbds);

  vtkNew<vtkLookupTable> lut;
  lut->SetValueRange(scalars->GetRange());
  lut->SetNanColor(1., 1., 0., 1.);
  lut->Build();

  vtkNew<vtkCompositePolyDataMapper2> mapper;
  mapper->SetInputConnection(source->GetOutputPort());
  mapper->SetLookupTable(lut);
  mapper->SetScalarVisibility(1);
  mapper->SetScalarRange(scalars->GetRange());
  mapper->SetColorMissingArraysWithNanColor(true);
  mapper->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS,vtkDataSetAttributes::SCALARS);

  vtkNew<vtkActor> actor;
  actor->SetMapper(mapper);
  actor->GetProperty()->SetColor(0., 0., 1.);
  actor->GetProperty()->SetAmbientColor(0.2, 0.2, 1.0);
  actor->GetProperty()->SetDiffuseColor(1.0, 0.65, 0.7);
  actor->GetProperty()->SetSpecularColor(1.0, 1.0, 1.0);
  actor->GetProperty()->SetSpecular(0.5);
  actor->GetProperty()->SetDiffuse(0.7);
  actor->GetProperty()->SetAmbient(0.5);
  actor->GetProperty()->SetSpecularPower(20.0);
  actor->GetProperty()->SetOpacity(1.0);
  FillShaderProperty( actor.GetPointer() );
  renderer->AddActor(actor);

  vtkNew<vtkRenderWindowInteractor> iren;
  vtkNew<vtkRenderWindow> renWin;
  renWin->SetMultiSamples(0);
  iren->SetRenderWindow(renWin);
  renWin->AddRenderer(renderer);

  renWin->SetSize(500,500);
  renderer->GetActiveCamera()->SetPosition(0,0,1);
  renderer->GetActiveCamera()->SetFocalPoint(0,0,0);
  renderer->GetActiveCamera()->SetViewUp(0,1,0);
  renderer->ResetCamera();

  renWin->Render();

  int retVal = vtkRegressionTestImageThreshold( renWin,15);
  if ( retVal == vtkRegressionTester::DO_INTERACTOR)
  {
    iren->Start();
  }

  return !retVal;
}