TestUserShader2.cxx 6.86 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*=========================================================================

  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 "vtkActor.h"
16 17 18 19
#include "vtkCamera.h"
#include "vtkCommand.h"
#include "vtkMath.h"
#include "vtkNew.h"
20 21
#include "vtkOpenGLPolyDataMapper.h"
#include "vtkPLYReader.h"
22
#include "vtkProperty.h"
23
#include "vtkRegressionTestImage.h"
24 25 26 27
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkShaderProgram.h"
28
#include "vtkTestUtilities.h"
29
#include "vtkTimerLog.h"
Ken Martin's avatar
Ken Martin committed
30
#include "vtkTriangleMeshPointNormals.h"
31

32 33 34 35 36 37 38 39 40 41 42 43 44

#define VTK_CREATE(type, name) \
  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()

// -----------------------------------------------------------------------
// Update a uniform in the shader for each render. We do this with a
// callback for the UpdateShaderEvent
class vtkShaderCallback : public vtkCommand
{
public:
  static vtkShaderCallback *New()
    { return new vtkShaderCallback; }
  vtkRenderer *Renderer;
45
  void Execute(vtkObject *, unsigned long, void* calldata) override
46
  {
47
    vtkShaderProgram *program = reinterpret_cast<vtkShaderProgram*>(calldata);
48 49 50 51 52 53

    float diffuseColor[3];

#if 0  // trippy mode
    float inputHSV[3];
    double theTime = vtkTimerLog::GetUniversalTime();
54
    double twopi = 2.0*vtkMath::Pi();
55 56 57 58 59 60 61

    inputHSV[0] = sin(twopi*fmod(theTime,3.0)/3.0)/4.0 + 0.25;
    inputHSV[1] = sin(twopi*fmod(theTime,4.0)/4.0)/2.0 + 0.5;
    inputHSV[2] = 0.7*(sin(twopi*fmod(theTime,19.0)/19.0)/2.0 + 0.5);
    vtkMath::HSVToRGB(inputHSV,diffuseColor);
    cellBO->Program->SetUniform3f("diffuseColorUniform", diffuseColor);

Ken Martin's avatar
Ken Martin committed
62
    if (this->Renderer)
63
    {
Ken Martin's avatar
Ken Martin committed
64 65 66 67 68 69 70 71 72 73 74
      inputHSV[0] = sin(twopi*fmod(theTime,5.0)/5.0)/4.0 + 0.75;
      inputHSV[1] = sin(twopi*fmod(theTime,7.0)/7.0)/2.0 + 0.5;
      inputHSV[2] = 0.5*(sin(twopi*fmod(theTime,17.0)/17.0)/2.0 + 0.5);
      vtkMath::HSVToRGB(inputHSV,diffuseColor);
      this->Renderer->SetBackground(diffuseColor[0], diffuseColor[1], diffuseColor[2]);

      inputHSV[0] = sin(twopi*fmod(theTime,11.0)/11.0)/2.0+0.5;
      inputHSV[1] = sin(twopi*fmod(theTime,13.0)/13.0)/2.0 + 0.5;
      inputHSV[2] = 0.5*(sin(twopi*fmod(theTime,17.0)/17.0)/2.0 + 0.5);
      vtkMath::HSVToRGB(inputHSV,diffuseColor);
      this->Renderer->SetBackground2(diffuseColor[0], diffuseColor[1], diffuseColor[2]);
75
    }
76 77 78 79
#else
    diffuseColor[0] = 0.4;
    diffuseColor[1] = 0.7;
    diffuseColor[2] = 0.6;
80
    program->SetUniform3f("diffuseColorUniform", diffuseColor);
81
#endif
82
  }
83

84
  vtkShaderCallback() { this->Renderer = nullptr; }
85
};
86 87 88 89 90 91 92 93 94 95

//----------------------------------------------------------------------------
int TestUserShader2(int argc, char *argv[])
{
  vtkNew<vtkActor> actor;
  vtkNew<vtkRenderer> renderer;
  vtkNew<vtkOpenGLPolyDataMapper> mapper;
  renderer->SetBackground(0.0, 0.0, 0.0);
  vtkNew<vtkRenderWindow> renderWindow;
  renderWindow->SetSize(400, 400);
96 97
  renderWindow->AddRenderer(renderer);
  renderer->AddActor(actor);
98
  renderer->GradientBackgroundOn();
99
  vtkNew<vtkRenderWindowInteractor>  iren;
100
  iren->SetRenderWindow(renderWindow);
101 102 103 104 105 106 107

  const char* fileName = vtkTestUtilities::ExpandDataFileName(argc, argv,
                                                               "Data/dragon.ply");
  vtkNew<vtkPLYReader> reader;
  reader->SetFileName(fileName);
  reader->Update();

108 109
  delete [] fileName;

Ken Martin's avatar
Ken Martin committed
110
  vtkNew<vtkTriangleMeshPointNormals> norms;
111 112 113 114
  norms->SetInputConnection(reader->GetOutputPort());
  norms->Update();

  mapper->SetInputConnection(norms->GetOutputPort());
115
  actor->SetMapper(mapper);
116 117 118 119 120 121 122 123 124
  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);

125 126 127 128 129 130 131 132
  // Clear all custom shader tag replacements
  // The following code is mainly for regression testing as we do not have any
  // custom shader replacements.
  mapper->ClearAllShaderReplacements(vtkShader::Vertex);
  mapper->ClearAllShaderReplacements(vtkShader::Fragment);
  mapper->ClearAllShaderReplacements(vtkShader::Geometry);
  mapper->ClearAllShaderReplacements();

133 134 135 136 137 138
  // Use our own hardcoded shader code. Generally this is a bad idea in a
  // general purpose program as there are so many things VTK supports that
  // hardcoded shaders will not handle depth peeling, picking, etc, but if you
  // know what your data will be like it can be very useful. The mapper will set
  // a bunch of uniforms regardless of if you are using them. But feel free to
  // use them :-)
139 140
  mapper->SetVertexShaderCode(
    "//VTK::System::Dec\n"  // always start with this line
141
    "in vec4 vertexMC;\n"
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
    // use the default normal decl as the mapper
    // will then provide the normalMatrix uniform
    // which we use later on
    "//VTK::Normal::Dec\n"
    "uniform mat4 MCDCMatrix;\n"
    "void main () {\n"
    "  normalVCVSOutput = normalMatrix * normalMC;\n"
    // do something weird with the vertex positions
    // this will mess up your head if you keep
    // rotating and looking at it, very trippy
    "  vec4 tmpPos = MCDCMatrix * vertexMC;\n"
    "  gl_Position = tmpPos*vec4(0.2+0.8*abs(tmpPos.x),0.2+0.8*abs(tmpPos.y),1.0,1.0);\n"
    "}\n"
    );
  mapper->SetFragmentShaderCode(
    "//VTK::System::Dec\n"  // always start with this line
    "//VTK::Output::Dec\n"  // always have this line in your FS
159
    "in vec3 normalVCVSOutput;\n"
160
    "uniform vec3 diffuseColorUniform;\n"
161 162 163
    "void main () {\n"
    "  float df = max(0.0, normalVCVSOutput.z);\n"
    "  float sf = pow(df, 20.0);\n"
164
    "  vec3 diffuse = df * diffuseColorUniform;\n"
165
    "  vec3 specular = sf * vec3(0.4,0.4,0.4);\n"
166
    "  gl_FragData[0] = vec4(0.3*abs(normalVCVSOutput) + 0.7*diffuse + specular, 1.0);\n"
167 168 169
    "}\n"
    );

170 171
  // Setup a callback to change some uniforms
  VTK_CREATE(vtkShaderCallback, myCallback);
172
  myCallback->Renderer = renderer;
173
  mapper->AddObserver(vtkCommand::UpdateShaderEvent, myCallback);
174

175 176 177 178 179 180 181 182
  renderWindow->Render();
  renderer->GetActiveCamera()->SetPosition(-0.2,0.4,1);
  renderer->GetActiveCamera()->SetFocalPoint(0,0,0);
  renderer->GetActiveCamera()->SetViewUp(0,1,0);
  renderer->ResetCamera();
  renderer->GetActiveCamera()->Zoom(2.0);
  renderWindow->Render();

183
  int retVal = vtkRegressionTestImage( renderWindow );
184
  if ( retVal == vtkRegressionTester::DO_INTERACTOR)
185
  {
186
    iren->Start();
187
  }
188

189
  return !retVal;
190
}