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 #include "vtkOpenGLGlyph3DHelper.h"
15 
16 #include "vtkOpenGLHelper.h"
17 
18 #include "vtkBitArray.h"
19 #include "vtkCamera.h"
20 #include "vtkDataObject.h"
21 #include "vtkHardwareSelector.h"
22 #include "vtkMath.h"
23 #include "vtkMatrix3x3.h"
24 #include "vtkMatrix4x4.h"
25 #include "vtkNew.h"
26 #include "vtkObjectFactory.h"
27 #include "vtkOpenGLActor.h"
28 #include "vtkOpenGLBufferObject.h"
29 #include "vtkOpenGLCamera.h"
30 #include "vtkOpenGLError.h"
31 #include "vtkOpenGLIndexBufferObject.h"
32 #include "vtkOpenGLInstanceCulling.h"
33 #include "vtkOpenGLRenderWindow.h"
34 #include "vtkOpenGLRenderer.h"
35 #include "vtkOpenGLResourceFreeCallback.h"
36 #include "vtkOpenGLShaderCache.h"
37 #include "vtkOpenGLVertexArrayObject.h"
38 #include "vtkOpenGLVertexBufferObject.h"
39 #include "vtkOpenGLVertexBufferObjectGroup.h"
40 #include "vtkPolyData.h"
41 #include "vtkProperty.h"
42 #include "vtkShader.h"
43 #include "vtkShaderProgram.h"
44 #include "vtkTransform.h"
45 #include "vtkTransformFeedback.h"
46 
47 #include "vtkGlyph3DVS.h"
48 
49 #include <algorithm>
50 #include <numeric>
51 
52 //-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkOpenGLGlyph3DHelper)53 vtkStandardNewMacro(vtkOpenGLGlyph3DHelper)
54 
55 //-----------------------------------------------------------------------------
56 vtkOpenGLGlyph3DHelper::vtkOpenGLGlyph3DHelper()
57 {
58   this->UsingInstancing = false;
59   this->PopulateSelectionSettings = 0;
60 }
61 
62 // ---------------------------------------------------------------------------
63 // Description:
64 // Release any graphics resources that are being consumed by this mapper.
ReleaseGraphicsResources(vtkWindow * window)65 void vtkOpenGLGlyph3DHelper::ReleaseGraphicsResources(vtkWindow *window)
66 {
67   this->NormalMatrixBuffer->ReleaseGraphicsResources();
68   this->MatrixBuffer->ReleaseGraphicsResources();
69   this->ColorBuffer->ReleaseGraphicsResources();
70   this->Superclass::ReleaseGraphicsResources(window);
71 }
72 
73 //-----------------------------------------------------------------------------
GetShaderTemplate(std::map<vtkShader::Type,vtkShader * > shaders,vtkRenderer * ren,vtkActor * actor)74 void vtkOpenGLGlyph3DHelper::GetShaderTemplate(
75     std::map<vtkShader::Type, vtkShader *> shaders,
76     vtkRenderer *ren, vtkActor *actor)
77 {
78   this->Superclass::GetShaderTemplate(shaders,ren,actor);
79 
80   shaders[vtkShader::Vertex]->SetSource(vtkGlyph3DVS);
81 }
82 
ReplaceShaderPositionVC(std::map<vtkShader::Type,vtkShader * > shaders,vtkRenderer * ren,vtkActor * actor)83 void vtkOpenGLGlyph3DHelper::ReplaceShaderPositionVC(
84   std::map<vtkShader::Type, vtkShader *> shaders,
85   vtkRenderer *ren, vtkActor *actor)
86 {
87   std::string VSSource = shaders[vtkShader::Vertex]->GetSource();
88 
89   if (this->LastLightComplexity[this->LastBoundBO] > 0)
90   {
91     // we use vertex instead of vertexMC
92     vtkShaderProgram::Substitute(VSSource,
93       "//VTK::PositionVC::Impl",
94       "vertexVCVSOutput = MCVCMatrix * vertex;\n"
95       "  gl_Position = MCDCMatrix * vertex;\n");
96   }
97   else
98   {
99     vtkShaderProgram::Substitute(VSSource,
100       "//VTK::PositionVC::Impl",
101       "gl_Position = MCDCMatrix * vertex;\n");
102   }
103 
104   shaders[vtkShader::Vertex]->SetSource(VSSource);
105 
106   this->Superclass::ReplaceShaderPositionVC(shaders,ren,actor);
107 }
108 
ReplaceShaderColor(std::map<vtkShader::Type,vtkShader * > shaders,vtkRenderer * ren,vtkActor * actor)109 void vtkOpenGLGlyph3DHelper::ReplaceShaderColor(
110   std::map<vtkShader::Type, vtkShader *> shaders,
111   vtkRenderer *ren, vtkActor *actor)
112 {
113   std::string VSSource = shaders[vtkShader::Vertex]->GetSource();
114   std::string FSSource = shaders[vtkShader::Fragment]->GetSource();
115   std::string GSSource = shaders[vtkShader::Geometry]->GetSource();
116 
117   // deal with color
118   if (this->UsingInstancing)
119   {
120     vtkShaderProgram::Substitute(VSSource,
121       "//VTK::Color::Dec",
122       "in vec4 glyphColor;\n"
123       "out vec4 vertexColorVSOutput;");
124     vtkShaderProgram::Substitute(GSSource,
125       "//VTK::Color::Dec",
126       "in vec4 vertexColorVSOutput[];\n"
127       "out vec4 vertexColorGSOutput;");
128     vtkShaderProgram::Substitute(GSSource,
129       "//VTK::Color::Impl",
130       "vertexColorGSOutput = vertexColorVSOutput[i];");
131     vtkShaderProgram::Substitute(VSSource,"//VTK::Color::Impl",
132       "vertexColorVSOutput =  glyphColor;");
133     vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Dec",
134       "in vec4 vertexColorVSOutput;\n"
135       "//VTK::Color::Dec", false);
136   }
137   else
138   {
139     vtkShaderProgram::Substitute(VSSource,
140       "//VTK::Color::Dec", "");
141     vtkShaderProgram::Substitute(FSSource,
142       "//VTK::Color::Dec",
143       "uniform vec4 glyphColor;\n"
144       "//VTK::Color::Dec", false);
145     vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Impl",
146       "vec4 vertexColorVSOutput = glyphColor;\n"
147       "//VTK::Color::Impl", false);
148   }
149 
150   // now handle scalar coloring
151   if(!this->DrawingEdgesOrVertices)
152   {
153     vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Impl",
154       "//VTK::Color::Impl\n"
155       "  diffuseColor = diffuseIntensity * vertexColorVSOutput.rgb;\n"
156       "  ambientColor = ambientIntensity * vertexColorVSOutput.rgb;\n"
157       "  opacity = opacity * vertexColorVSOutput.a;");
158   }
159 
160   if (this->UsingInstancing)
161   {
162     vtkShaderProgram::Substitute(VSSource,
163        "//VTK::Glyph::Dec",
164        "in mat4 GCMCMatrix;");
165   }
166   else
167   {
168     vtkShaderProgram::Substitute(VSSource,
169       "//VTK::Glyph::Dec",
170       "uniform mat4 GCMCMatrix;");
171   }
172   vtkShaderProgram::Substitute(VSSource,
173     "//VTK::Glyph::Impl",
174     "vec4 vertex = GCMCMatrix * vertexMC;\n");
175 
176   shaders[vtkShader::Vertex]->SetSource(VSSource);
177   shaders[vtkShader::Fragment]->SetSource(FSSource);
178   shaders[vtkShader::Geometry]->SetSource(GSSource);
179 
180   this->Superclass::ReplaceShaderColor(shaders,ren,actor);
181 }
182 
ReplaceShaderNormal(std::map<vtkShader::Type,vtkShader * > shaders,vtkRenderer * ren,vtkActor * actor)183 void vtkOpenGLGlyph3DHelper::ReplaceShaderNormal(
184   std::map<vtkShader::Type, vtkShader *> shaders,
185   vtkRenderer *ren, vtkActor *actor)
186 {
187   std::string VSSource = shaders[vtkShader::Vertex]->GetSource();
188   std::string FSSource = shaders[vtkShader::Fragment]->GetSource();
189 
190   // new code for normal matrix if we have normals
191   if (this->VBOs->GetNumberOfComponents("normalMC") == 3)
192   {
193     if (this->UsingInstancing)
194     {
195       vtkShaderProgram::Substitute(VSSource,
196          "//VTK::Normal::Dec",
197          "uniform mat3 normalMatrix;\n"
198          "in vec3 normalMC;\n"
199          "in mat3 glyphNormalMatrix;\n"
200          "out vec3 normalVCVSOutput;");
201     }
202     else
203     {
204       vtkShaderProgram::Substitute(VSSource,
205          "//VTK::Normal::Dec",
206          "uniform mat3 normalMatrix;\n"
207          "in vec3 normalMC;\n"
208          "uniform mat3 glyphNormalMatrix;\n"
209          "out vec3 normalVCVSOutput;");
210     }
211     vtkShaderProgram::Substitute(VSSource, "//VTK::Normal::Impl",
212       "normalVCVSOutput = normalMatrix * glyphNormalMatrix * normalMC;");
213   }
214 
215   shaders[vtkShader::Vertex]->SetSource(VSSource);
216   shaders[vtkShader::Fragment]->SetSource(FSSource);
217 
218   this->Superclass::ReplaceShaderNormal(shaders,ren,actor);
219 }
220 
221 
ReplaceShaderClip(std::map<vtkShader::Type,vtkShader * > shaders,vtkRenderer * ren,vtkActor * actor)222 void vtkOpenGLGlyph3DHelper::ReplaceShaderClip(
223   std::map<vtkShader::Type, vtkShader *> shaders,
224   vtkRenderer *ren, vtkActor *actor)
225 {
226   std::string VSSource = shaders[vtkShader::Vertex]->GetSource();
227 
228   // override one part of the clipping code
229   if (this->GetNumberOfClippingPlanes())
230   {
231     // add all the clipping planes
232     int numClipPlanes = this->GetNumberOfClippingPlanes();
233     if (numClipPlanes > 6)
234     {
235       vtkErrorMacro("OpenGL has a limit of 6 clipping planes");
236     }
237 
238     vtkShaderProgram::Substitute(VSSource,
239        "//VTK::Clip::Impl",
240        "for (int planeNum = 0; planeNum < numClipPlanes; planeNum++)\n"
241        "    {\n"
242        "    clipDistancesVSOutput[planeNum] = dot(clipPlanes[planeNum], vertex);\n"
243        "    }\n");
244   }
245 
246   shaders[vtkShader::Vertex]->SetSource(VSSource);
247 
248   this->Superclass::ReplaceShaderClip(shaders,ren,actor);
249 }
250 
ReplaceShaderPicking(std::map<vtkShader::Type,vtkShader * > shaders,vtkRenderer *,vtkActor *)251 void vtkOpenGLGlyph3DHelper::ReplaceShaderPicking(
252   std::map<vtkShader::Type, vtkShader *> shaders,
253   vtkRenderer *, vtkActor *)
254 {
255   std::string FSSource = shaders[vtkShader::Fragment]->GetSource();
256 
257   if (this->LastSelectionState >= vtkHardwareSelector::MIN_KNOWN_PASS)
258   {
259     vtkShaderProgram::Substitute(FSSource, "//VTK::Picking::Dec",
260       "uniform vec3 mapperIndex;");
261     vtkShaderProgram::Substitute(FSSource,
262       "//VTK::Picking::Impl",
263       "  gl_FragData[0] = vec4(mapperIndex,1.0);\n");
264   }
265   shaders[vtkShader::Fragment]->SetSource(FSSource);
266 }
267 
GlyphRender(vtkRenderer * ren,vtkActor * actor,vtkIdType numPts,std::vector<unsigned char> & colors,std::vector<float> & matrices,std::vector<float> & normalMatrices,std::vector<vtkIdType> & pickIds,vtkMTimeType pointMTime,bool culling)268 void vtkOpenGLGlyph3DHelper::GlyphRender(
269   vtkRenderer* ren,
270   vtkActor* actor,
271   vtkIdType numPts,
272   std::vector<unsigned char> &colors,
273   std::vector<float> &matrices,
274   std::vector<float> &normalMatrices,
275   std::vector<vtkIdType> &pickIds,
276   vtkMTimeType pointMTime,
277   bool culling)
278 {
279   this->ResourceCallback->RegisterGraphicsResources(
280     static_cast<vtkOpenGLRenderWindow *>(ren->GetRenderWindow()));
281 
282   this->UsingInstancing = false;
283 
284   vtkHardwareSelector* selector = ren->GetSelector();
285 
286   if (!selector && !ren->GetRenderWindow()->GetIsPicking()
287       && GLEW_ARB_instanced_arrays)
288   {
289     // if there is no triangle, culling is useless.
290     // GLEW_ARB_gpu_shader5 is needed by the culling shader.
291 #ifndef GL_ES_VERSION_3_0
292     if (this->CurrentInput->GetNumberOfPolys() <= 0 || !GLEW_ARB_gpu_shader5 || !GLEW_ARB_transform_feedback3)
293     {
294       culling = false;
295     }
296 #else
297     // disable culling on OpenGL ES
298     culling = false;
299 #endif
300 
301     this->GlyphRenderInstances(ren, actor, numPts, colors,
302       matrices, normalMatrices, pointMTime, culling);
303     return;
304   }
305 
306   bool selecting_points = selector && (selector->GetFieldAssociation() ==
307     vtkDataObject::FIELD_ASSOCIATION_POINTS);
308 
309   int representation = actor->GetProperty()->GetRepresentation();
310 
311   this->RenderPieceStart(ren,actor);
312 
313   if (selecting_points)
314   {
315 #if GL_ES_VERSION_3_0 != 1
316     glPointSize(6.0);
317 #endif
318     representation = GL_POINTS;
319   }
320 
321   bool draw_surface_with_edges =
322     (actor->GetProperty()->GetEdgeVisibility() && representation == VTK_SURFACE) && !selector;
323   int numVerts = this->VBOs->GetNumberOfTuples("vertexMC");
324   for (int i = PrimitiveStart;
325        i < (draw_surface_with_edges ? PrimitiveEnd : PrimitiveTriStrips + 1); i++)
326   {
327     this->DrawingEdgesOrVertices = (i > PrimitiveTriStrips ? true : false);
328     if (this->Primitives[i].IBO->IndexCount)
329     {
330       this->UpdateShaders(this->Primitives[i], ren, actor);
331       GLenum mode = this->GetOpenGLMode(representation, i);
332       this->Primitives[i].IBO->Bind();
333       for (vtkIdType inPtId = 0; inPtId < numPts; inPtId++)
334       {
335         // handle the middle
336         vtkShaderProgram *program = this->Primitives[i].Program;
337 
338         if (!program)
339         {
340           return;
341         }
342 
343         // Apply the extra transform
344         program->SetUniformMatrix4x4("GCMCMatrix", &(matrices[inPtId*16]));
345 
346         // for lit shaders set normal matrix
347         if (this->LastLightComplexity[this->LastBoundBO] > 0 &&
348             this->VBOs->GetNumberOfComponents("normalMC") == 3 &&
349             !this->UsingInstancing)
350         {
351           program->SetUniformMatrix3x3("glyphNormalMatrix", &(normalMatrices[inPtId*9]));
352         }
353 
354         program->SetUniform4uc("glyphColor", &(colors[inPtId*4]));
355 
356         if (selector)
357         {
358           if (selector->GetCurrentPass() == vtkHardwareSelector::POINT_ID_LOW24 ||
359               selector->GetCurrentPass() == vtkHardwareSelector::POINT_ID_HIGH24 ||
360               selector->GetCurrentPass() == vtkHardwareSelector::CELL_ID_LOW24 ||
361               selector->GetCurrentPass() == vtkHardwareSelector::CELL_ID_HIGH24)
362           {
363             selector->SetPropColorValue(pickIds[inPtId]);
364           }
365           program->SetUniform3f("mapperIndex", selector->GetPropColorValue());
366         }
367 
368         glDrawRangeElements(mode, 0,
369                             static_cast<GLuint>(numVerts - 1),
370                             static_cast<GLsizei>(this->Primitives[i].IBO->IndexCount),
371                             GL_UNSIGNED_INT,
372                             nullptr);
373       }
374       this->Primitives[i].IBO->Release();
375     }
376   }
377   this->RenderPieceFinish(ren,actor);
378 }
379 
380 //-----------------------------------------------------------------------------
SetMapperShaderParameters(vtkOpenGLHelper & cellBO,vtkRenderer * ren,vtkActor * actor)381 void vtkOpenGLGlyph3DHelper::SetMapperShaderParameters(vtkOpenGLHelper &cellBO,
382                                                          vtkRenderer *ren, vtkActor *actor)
383 {
384   this->Superclass::SetMapperShaderParameters(cellBO,ren,actor);
385 
386   vtkHardwareSelector* selector = ren->GetSelector();
387   if (selector)
388   {
389     cellBO.Program->SetUniform3f("mapperIndex", selector->GetPropColorValue());
390   }
391 }
392 
GlyphRenderInstances(vtkRenderer * ren,vtkActor * actor,vtkIdType numPts,std::vector<unsigned char> & colors,std::vector<float> & matrices,std::vector<float> & normalMatrices,vtkMTimeType pointMTime,bool culling)393 void vtkOpenGLGlyph3DHelper::GlyphRenderInstances(
394     vtkRenderer* ren, vtkActor* actor, vtkIdType numPts,
395     std::vector<unsigned char> &colors, std::vector<float> &matrices,
396     std::vector<float> &normalMatrices,
397     vtkMTimeType pointMTime, bool culling)
398 {
399   this->UsingInstancing = true;
400   this->RenderPieceStart(ren,actor);
401   int representation = actor->GetProperty()->GetRepresentation();
402 
403   bool withNormals = (this->VBOs->GetNumberOfComponents("normalMC") == 3);
404 
405   // update the VBOs if needed
406   if (pointMTime > this->InstanceBuffersBuildTime.GetMTime())
407   {
408     this->MatrixBuffer->Upload(matrices, vtkOpenGLBufferObject::ArrayBuffer);
409 
410     if (withNormals)
411     {
412       this->NormalMatrixBuffer->Upload(
413         normalMatrices, vtkOpenGLBufferObject::ArrayBuffer);
414     }
415 
416     this->ColorBuffer->Upload(colors, vtkOpenGLBufferObject::ArrayBuffer);
417     this->InstanceBuffersBuildTime.Modified();
418   }
419 
420   bool draw_surface_with_edges =
421     (actor->GetProperty()->GetEdgeVisibility() && representation == VTK_SURFACE);
422   for (int i = PrimitiveStart;
423        i < (draw_surface_with_edges ? PrimitiveEnd : PrimitiveTriStrips + 1); i++)
424   {
425     this->DrawingEdgesOrVertices = (i > PrimitiveTriStrips ? true : false);
426     if (this->Primitives[i].IBO->IndexCount)
427     {
428       GLenum mode = this->GetOpenGLMode(representation, i);
429 
430       // culling
431       if (culling)
432       {
433         this->BuildCullingShaders(ren, actor, numPts, withNormals);
434         if (!this->InstanceCulling->GetHelper().Program)
435         {
436           return;
437         }
438 
439         this->InstanceCulling->RunCullingShaders(numPts, this->MatrixBuffer, this->ColorBuffer, this->NormalMatrixBuffer);
440 
441         // draw each LOD
442 
443         this->UpdateShaders(this->Primitives[i], ren, actor);
444         if (!this->Primitives[i].Program)
445         {
446           return;
447         }
448 
449         size_t stride = (withNormals ? 29 : 20) * sizeof(float);
450 
451         this->Primitives[i].VAO->Bind();
452 
453         for (vtkIdType j=0; j<this->InstanceCulling->GetNumberOfLOD(); j++)
454         {
455           if (this->InstanceCulling->GetLOD(j).NumberOfInstances == 0) continue;
456 
457           // add VBO of current instance in VAO
458           if (!this->Primitives[i].VAO->AddAttributeArray(
459                 this->Primitives[i].Program, this->InstanceCulling->GetLOD(j).PositionVBO,
460                 "vertexMC", 0, 4 * sizeof(float), VTK_FLOAT, 4, false))
461           {
462             vtkErrorMacro("Error setting 'vertexMC' in shader VAO.");
463           }
464 
465           if (withNormals)
466           {
467             if (!this->Primitives[i].VAO->AddAttributeArray(
468                   this->Primitives[i].Program, this->InstanceCulling->GetLOD(j).NormalVBO,
469                   "normalMC", 0, 3 * sizeof(float), VTK_FLOAT, 3, false))
470             {
471               vtkErrorMacro("Error setting 'normalMC' in shader VAO.");
472             }
473           }
474 
475           // add instances attributes based on transform feedback buffers
476           if (!this->Primitives[i].VAO->AddAttributeArrayWithDivisor(
477                 this->Primitives[i].Program, this->InstanceCulling->GetLODBuffer(j),
478                 "glyphColor", 16 * sizeof(float), stride, VTK_FLOAT, 4, false, 1, false))
479           {
480             vtkErrorMacro("Error setting 'diffuse color' in shader VAO.");
481           }
482 
483           if (!this->Primitives[i].VAO->AddAttributeMatrixWithDivisor(
484               this->Primitives[i].Program, this->InstanceCulling->GetLODBuffer(j),
485                 "GCMCMatrix", 0, stride, VTK_FLOAT, 4, false, 1, 4 * sizeof(float)))
486           {
487             vtkErrorMacro("Error setting 'GCMCMatrix' in shader VAO.");
488           }
489 
490           if (withNormals)
491           {
492             if (!this->Primitives[i].VAO->AddAttributeMatrixWithDivisor(
493                   this->Primitives[i].Program, this->InstanceCulling->GetLODBuffer(j),
494                   "glyphNormalMatrix", 20 * sizeof(float), stride, VTK_FLOAT, 3, false, 1, 3 * sizeof(float)))
495             {
496               vtkErrorMacro("Error setting 'glyphNormalMatrix' in shader VAO.");
497             }
498           }
499 
500           if (this->InstanceCulling->GetLOD(j).IBO->IndexCount > 0)
501           {
502             this->InstanceCulling->GetLOD(j).IBO->Bind();
503 
504 #if GL_ES_VERSION_3_0 == 1
505             glDrawElementsInstanced(mode,
506               static_cast<GLsizei>(this->InstanceCulling->GetLOD(j).IBO->IndexCount),
507               GL_UNSIGNED_INT,
508               nullptr,
509               this->InstanceCulling->GetLOD(j).NumberOfInstances);
510 #else
511             glDrawElementsInstancedARB(mode,
512               static_cast<GLsizei>(this->InstanceCulling->GetLOD(j).IBO->IndexCount),
513               GL_UNSIGNED_INT,
514               nullptr,
515               this->InstanceCulling->GetLOD(j).NumberOfInstances);
516 #endif
517             this->InstanceCulling->GetLOD(j).IBO->Release();
518           }
519           else
520           {
521 #if GL_ES_VERSION_3_0 == 1
522             glDrawArraysInstanced(GL_POINTS, 0, 1,
523               this->InstanceCulling->GetLOD(j).NumberOfInstances);
524 #else
525             glDrawArraysInstancedARB(GL_POINTS, 0, 1,
526               this->InstanceCulling->GetLOD(j).NumberOfInstances);
527 #endif
528           }
529         }
530       }
531       else
532       {
533         this->UpdateShaders(this->Primitives[i], ren, actor);
534         if (!this->Primitives[i].Program)
535         {
536           return;
537         }
538 
539         // do the superclass and then reset a couple values
540         if ((this->InstanceBuffersBuildTime > this->InstanceBuffersLoadTime ||
541               this->Primitives[i].ShaderSourceTime > this->InstanceBuffersLoadTime))
542         {
543           this->Primitives[i].VAO->Bind();
544 
545           this->MatrixBuffer->Bind();
546           if (!this->Primitives[i].VAO->AddAttributeMatrixWithDivisor(
547             this->Primitives[i].Program, this->MatrixBuffer,
548               "GCMCMatrix", 0, 16 * sizeof(float), VTK_FLOAT, 4, false, 1, 4 * sizeof(float)))
549           {
550             vtkErrorMacro("Error setting 'GCMCMatrix' in shader VAO.");
551           }
552           this->MatrixBuffer->Release();
553 
554           if (withNormals && this->Primitives[i].Program->IsAttributeUsed("glyphNormalMatrix"))
555           {
556             this->NormalMatrixBuffer->Bind();
557             if (!this->Primitives[i].VAO->AddAttributeMatrixWithDivisor(
558                   this->Primitives[i].Program, this->NormalMatrixBuffer,
559                   "glyphNormalMatrix", 0, 9 * sizeof(float), VTK_FLOAT, 3, false, 1, 3 * sizeof(float)))
560             {
561               vtkErrorMacro("Error setting 'glyphNormalMatrix' in shader VAO.");
562             }
563             this->NormalMatrixBuffer->Release();
564           }
565 
566           if (this->Primitives[i].Program->IsAttributeUsed("glyphColor"))
567           {
568             this->ColorBuffer->Bind();
569             if (!this->Primitives[i].VAO->AddAttributeArrayWithDivisor(
570                   this->Primitives[i].Program, this->ColorBuffer,
571                   "glyphColor", 0, 4 * sizeof(unsigned char), VTK_UNSIGNED_CHAR, 4, true, 1, false))
572             {
573               vtkErrorMacro("Error setting 'diffuse color' in shader VAO.");
574             }
575             this->ColorBuffer->Release();
576           }
577           this->InstanceBuffersLoadTime.Modified();
578         }
579 
580         this->Primitives[i].IBO->Bind();
581 
582 #if GL_ES_VERSION_3_0 == 1
583         glDrawElementsInstanced(mode,
584           static_cast<GLsizei>(this->Primitives[i].IBO->IndexCount),
585           GL_UNSIGNED_INT,
586           nullptr,
587           numPts);
588 #else
589         glDrawElementsInstancedARB(mode,
590           static_cast<GLsizei>(this->Primitives[i].IBO->IndexCount),
591           GL_UNSIGNED_INT,
592           nullptr,
593           numPts);
594 #endif
595 
596         this->Primitives[i].IBO->Release();
597       }
598     }
599   }
600 
601   vtkOpenGLCheckErrorMacro("failed after Render");
602   this->RenderPieceFinish(ren, actor);
603 }
604 
605 //-----------------------------------------------------------------------------
BuildCullingShaders(vtkRenderer * ren,vtkActor * actor,vtkIdType numPts,bool withNormals)606 void vtkOpenGLGlyph3DHelper::BuildCullingShaders(vtkRenderer* ren, vtkActor* actor, vtkIdType numPts, bool withNormals)
607 {
608   vtkOpenGLRenderWindow* renWin = vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow());
609 
610   if (!this->InstanceCulling->GetHelper().Program)
611   {
612     this->InstanceCulling->InitLOD(this->CurrentInput);
613 
614     for (auto& lod : this->LODs)
615     {
616       this->InstanceCulling->AddLOD(lod.first, lod.second);
617     }
618   }
619 
620   this->InstanceCulling->BuildCullingShaders(renWin->GetShaderCache(), numPts, withNormals);
621 
622   if (this->InstanceCulling->GetHelper().Program)
623   {
624     this->SetCameraShaderParameters(this->InstanceCulling->GetHelper(), ren, actor);
625 
626     double* bounds = this->CurrentInput->GetBounds();
627     float BBoxSize[4] = { static_cast<float>(bounds[1] - bounds[0]),
628                           static_cast<float>(bounds[3] - bounds[2]),
629                           static_cast<float>(bounds[5] - bounds[4]),
630                           0.f };
631 
632     this->InstanceCulling->GetHelper().Program->SetUniform4f("BBoxSize", BBoxSize);
633   }
634 }
635 
636 //-----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)637 void vtkOpenGLGlyph3DHelper::PrintSelf(ostream& os, vtkIndent indent)
638 {
639   this->Superclass::PrintSelf(os, indent);
640 }
641 
642 //-----------------------------------------------------------------------------
SetLODs(std::vector<std::pair<float,float>> & lods)643 void vtkOpenGLGlyph3DHelper::SetLODs(std::vector<std::pair<float, float> >& lods)
644 {
645   this->LODs = lods;
646 }
647 
648 //-----------------------------------------------------------------------------
SetLODColoring(bool val)649 void vtkOpenGLGlyph3DHelper::SetLODColoring(bool val)
650 {
651   this->InstanceCulling->SetColorLOD(val);
652 }
653