1 /*=========================================================================
2
3 Program: Visualization Toolkit
4
5 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
6 All rights reserved.
7 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
8
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the above copyright notice for more information.
12
13 =========================================================================*/
14
15 #include "vtkActor.h"
16 #include "vtkCamera.h"
17 #include "vtkCommand.h"
18 #include "vtkMath.h"
19 #include "vtkNew.h"
20 #include "vtkOpenGLPolyDataMapper.h"
21 #include "vtkPLYReader.h"
22 #include "vtkProperty.h"
23 #include "vtkRegressionTestImage.h"
24 #include "vtkRenderWindow.h"
25 #include "vtkRenderWindowInteractor.h"
26 #include "vtkRenderer.h"
27 #include "vtkShaderProgram.h"
28 #include "vtkShaderProperty.h"
29 #include "vtkTestUtilities.h"
30 #include "vtkTimerLog.h"
31 #include "vtkTriangleMeshPointNormals.h"
32
33 #define VTK_CREATE(type, name) vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
34
35 //------------------------------------------------------------------------------
36 // Update a uniform in the shader for each render. We do this with a
37 // callback for the UpdateShaderEvent
38 class vtkShaderCallback : public vtkCommand
39 {
40 public:
New()41 static vtkShaderCallback* New() { return new vtkShaderCallback; }
42 vtkRenderer* Renderer;
Execute(vtkObject *,unsigned long,void * calldata)43 void Execute(vtkObject*, unsigned long, void* calldata) override
44 {
45 vtkShaderProgram* program = reinterpret_cast<vtkShaderProgram*>(calldata);
46
47 float diffuseColor[3];
48
49 #if 0 // trippy mode
50 float inputHSV[3];
51 double theTime = vtkTimerLog::GetUniversalTime();
52 double twopi = 2.0*vtkMath::Pi();
53
54 inputHSV[0] = sin(twopi*fmod(theTime,3.0)/3.0)/4.0 + 0.25;
55 inputHSV[1] = sin(twopi*fmod(theTime,4.0)/4.0)/2.0 + 0.5;
56 inputHSV[2] = 0.7*(sin(twopi*fmod(theTime,19.0)/19.0)/2.0 + 0.5);
57 vtkMath::HSVToRGB(inputHSV,diffuseColor);
58 cellBO->Program->SetUniform3f("diffuseColorUniform", diffuseColor);
59
60 if (this->Renderer)
61 {
62 inputHSV[0] = sin(twopi*fmod(theTime,5.0)/5.0)/4.0 + 0.75;
63 inputHSV[1] = sin(twopi*fmod(theTime,7.0)/7.0)/2.0 + 0.5;
64 inputHSV[2] = 0.5*(sin(twopi*fmod(theTime,17.0)/17.0)/2.0 + 0.5);
65 vtkMath::HSVToRGB(inputHSV,diffuseColor);
66 this->Renderer->SetBackground(diffuseColor[0], diffuseColor[1], diffuseColor[2]);
67
68 inputHSV[0] = sin(twopi*fmod(theTime,11.0)/11.0)/2.0+0.5;
69 inputHSV[1] = sin(twopi*fmod(theTime,13.0)/13.0)/2.0 + 0.5;
70 inputHSV[2] = 0.5*(sin(twopi*fmod(theTime,17.0)/17.0)/2.0 + 0.5);
71 vtkMath::HSVToRGB(inputHSV,diffuseColor);
72 this->Renderer->SetBackground2(diffuseColor[0], diffuseColor[1], diffuseColor[2]);
73 }
74 #else
75 diffuseColor[0] = 0.4;
76 diffuseColor[1] = 0.7;
77 diffuseColor[2] = 0.6;
78 program->SetUniform3f("diffuseColorUniform", diffuseColor);
79 #endif
80 }
81
vtkShaderCallback()82 vtkShaderCallback() { this->Renderer = nullptr; }
83 };
84
85 //------------------------------------------------------------------------------
TestUserShader2(int argc,char * argv[])86 int TestUserShader2(int argc, char* argv[])
87 {
88 vtkNew<vtkActor> actor;
89 vtkNew<vtkRenderer> renderer;
90 vtkNew<vtkOpenGLPolyDataMapper> mapper;
91 renderer->SetBackground(0.0, 0.0, 0.0);
92 vtkNew<vtkRenderWindow> renderWindow;
93 renderWindow->SetSize(400, 400);
94 renderWindow->AddRenderer(renderer);
95 renderer->AddActor(actor);
96 renderer->GradientBackgroundOn();
97 vtkNew<vtkRenderWindowInteractor> iren;
98 iren->SetRenderWindow(renderWindow);
99
100 const char* fileName = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/dragon.ply");
101 vtkNew<vtkPLYReader> reader;
102 reader->SetFileName(fileName);
103 reader->Update();
104
105 delete[] fileName;
106
107 vtkNew<vtkTriangleMeshPointNormals> norms;
108 norms->SetInputConnection(reader->GetOutputPort());
109 norms->Update();
110
111 mapper->SetInputConnection(norms->GetOutputPort());
112 actor->SetMapper(mapper);
113 actor->GetProperty()->SetAmbientColor(0.2, 0.2, 1.0);
114 actor->GetProperty()->SetDiffuseColor(1.0, 0.65, 0.7);
115 actor->GetProperty()->SetSpecularColor(1.0, 1.0, 1.0);
116 actor->GetProperty()->SetSpecular(0.5);
117 actor->GetProperty()->SetDiffuse(0.7);
118 actor->GetProperty()->SetAmbient(0.5);
119 actor->GetProperty()->SetSpecularPower(20.0);
120 actor->GetProperty()->SetOpacity(1.0);
121
122 vtkShaderProperty* sp = actor->GetShaderProperty();
123
124 // Clear all custom shader tag replacements
125 // The following code is mainly for regression testing as we do not have any
126 // custom shader replacements.
127 sp->ClearAllVertexShaderReplacements();
128 sp->ClearAllFragmentShaderReplacements();
129 sp->ClearAllGeometryShaderReplacements();
130 sp->ClearAllShaderReplacements();
131
132 // Use our own hardcoded shader code. Generally this is a bad idea in a
133 // general purpose program as there are so many things VTK supports that
134 // hardcoded shaders will not handle depth peeling, picking, etc, but if you
135 // know what your data will be like it can be very useful. The mapper will set
136 // a bunch of uniforms regardless of if you are using them. But feel free to
137 // use them :-)
138 sp->SetVertexShaderCode(
139 "//VTK::System::Dec\n" // always start with this line
140 "in vec4 vertexMC;\n"
141 // use the default normal decl as the mapper
142 // will then provide the normalMatrix uniform
143 // which we use later on
144 "//VTK::Normal::Dec\n"
145 "uniform mat4 MCDCMatrix;\n"
146 "void main () {\n"
147 " normalVCVSOutput = normalMatrix * normalMC;\n"
148 // do something weird with the vertex positions
149 // this will mess up your head if you keep
150 // rotating and looking at it, very trippy
151 " vec4 tmpPos = MCDCMatrix * vertexMC;\n"
152 " gl_Position = tmpPos*vec4(0.2+0.8*abs(tmpPos.x),0.2+0.8*abs(tmpPos.y),1.0,1.0);\n"
153 "}\n");
154 sp->SetFragmentShaderCode(
155 "//VTK::System::Dec\n" // always start with this line
156 "//VTK::Output::Dec\n" // always have this line in your FS
157 "in vec3 normalVCVSOutput;\n"
158 "uniform vec3 diffuseColorUniform;\n"
159 "void main () {\n"
160 " float df = max(0.0, normalVCVSOutput.z);\n"
161 " float sf = pow(df, 20.0);\n"
162 " vec3 diffuse = df * diffuseColorUniform;\n"
163 " vec3 specular = sf * vec3(0.4,0.4,0.4);\n"
164 " gl_FragData[0] = vec4(0.3*abs(normalVCVSOutput) + 0.7*diffuse + specular, 1.0);\n"
165 "}\n");
166
167 // Setup a callback to change some uniforms
168 VTK_CREATE(vtkShaderCallback, myCallback);
169 myCallback->Renderer = renderer;
170 mapper->AddObserver(vtkCommand::UpdateShaderEvent, myCallback);
171
172 renderWindow->Render();
173 renderer->GetActiveCamera()->SetPosition(-0.2, 0.4, 1);
174 renderer->GetActiveCamera()->SetFocalPoint(0, 0, 0);
175 renderer->GetActiveCamera()->SetViewUp(0, 1, 0);
176 renderer->ResetCamera();
177 renderer->GetActiveCamera()->Zoom(2.0);
178 renderWindow->Render();
179
180 int retVal = vtkRegressionTestImage(renderWindow);
181 if (retVal == vtkRegressionTester::DO_INTERACTOR)
182 {
183 iren->Start();
184 }
185
186 return !retVal;
187 }
188